code:
# конец_боя
!WHEN FIGHT IS FINISHED WE WILL BE HERE
arena_mode = 0
killvar 'суперудар_сделан'

dynamic $броня_снять[$броня]

!Information about the latest actions of the player and opponents
$информация_о_бое = ''
if $боевая_обстановка ! '': $информация_о_бое += '<<$боевая_обстановка>>

'
$информация_о_бое += '<<$действия_игрока>>

'
$информация_о_бое += '<<$действия_врага[1]>>
'
$информация_о_бое += '<<$действия_врага[2]>>
'
$информация_о_бое += '<<$действия_врага[3]>>
'
$информация_о_бое += '<<$действия_врага[4]>>
'
$информация_о_бое += '<<$действия_врага[5]>>
'

if $place = 'edge_patrol':
	*p '
<img src = "content/pic/bg/<<$bg["edge_patrol"]>>.png">
'
elseif ui_style = 2:
	*p '

'
else
	*p '

'
end

*p '
<<$информация_о_бое>>
'

!control menu
if $extra_special_used = '': $extra_special_used = 'content/pic/buttons/shield_used.png'
if $extra_special_used = 'content/pic/buttons/dual_used.png': $extra_special_used = 'content/pic/buttons/shield_used.png'
if $extra_special_used = 'content/pic/buttons/net_used.png': $extra_special_used = 'content/pic/buttons/shield_used.png'
if $extra_special_used = 'content/pic/buttons/whip_used.png': $extra_special_used = 'content/pic/buttons/shield_used.png'
if $extra_special_used = 'content/pic/buttons/heavy_used.png': $extra_special_used = 'content/pic/buttons/shield_used.png'

if $итог_боя = 'победа':
	if ui_style = 2:
		$боевое_меню = "
"
	else
		$боевое_меню = "
"
	end
	if ui_style = 2:
		*p "
<img src = '<<$extra_special_used>>'>
"
	else
		*p "
<img src = '<<$extra_special_used>>'>
"
	end
end
if $итог_боя = 'бегство':
	if ui_style = 2:
		$боевое_меню = "
"
	else
		$боевое_меню = "
"
	end
	if ui_style = 2:
		*p "
<img src = '<<$extra_special_used>>'>
"
	else
		*p "
<img src = '<<$extra_special_used>>'>
"
	end
end
if $итог_боя = 'вырубился':
	if ui_style = 2:
		$боевое_меню = "
"
	else
		$боевое_меню = "
"
	end
	if ui_style = 2:
		*p "
<img src = '<<$extra_special_used>>'>
"
	else
		*p "
<img src = '<<$extra_special_used>>'>
"
	end
end
if $итог_боя = 'убит':
	if ui_style = 2:
		$боевое_меню = "
"
	else
		$боевое_меню = "
"
	end
	if ui_style = 2:
		*p "
<img src = '<<$extra_special_used>>'>
"
	else
		*p "
<img src = '<<$extra_special_used>>'>
"
	end
end

*p '
<<$боевое_меню>>
'

*p '
<img src = "<<$combatant_ava>>">
'
*p '
<img src = "<<$аватара_моба[$враг[текущий]]>>">
'

*p '
<<$combatant_name>>
'
*p '
<<$имя_врага[текущий]>>
'

*p '
<<$защита_описание[$защита[0]]>>
'
*p '

'
*p '
Doesn’t defend
'

*p '

'
*p '
<<здоровье_игрока>>
'
*p '

'
*p '
<<выносливость_игрока>>
'
*p '

'
*p '
<<дух_игрока>>
'
*p '

'
*p '
<<здоровье_врага[текущий]>>
'
*p '

'
*p '
<<выносливость_врага[текущий]>>
'
*p '

'
*p '
<<дух_врага[текущий]>>
'

--- конец_боя ---------------------------------


code:
# конец_раунда
!The round ends, and all caused effects has been calculated

!gradually pass all current good and bad effects
i = -1
:loop
if i < количество_врагов:
	i += 1
	if слабость[i] > 0: слабость[i] -= 1
	if скованность[i] > 0:скованность[i] -= 1
	if боль[i] > 0:боль[i] -= 1
	if шаткость[i] > 0:шаткость[i] -= 1
	if ошеломление[i] > 0:ошеломление[i] -= 1
	if рассеянность[i] > 0:рассеянность[i] -= 1
	if бешенство[i] > 0:бешенство[i] -= 1
	if разгон[i] > 0:разгон[i] -= 1
	if меткость[i] > 0:меткость[i] -= 1
	if адреналин[i] > 0:адреналин[i] -= 1
	if верткость[i] > 0:верткость[i] -= 1
	if внимание[i] > 0:внимание[i] -= 1
	jump 'loop'
end

!make damage and create status effect
if $класс_врага[текущий] ! 'пешка':
	if $тип_нанесенного_вреда = 'психический':
		if тонкое_тело[$враг[текущий]] = 1: здоровье_врага[текущий] -= нанесенный_вред
		if бесстрашный[$враг[текущий]] = 0: дух_врага[текущий] -= нанесенный_вред
		дух_игрока += нанесенный_вред/2
	elseif $тип_нанесенного_вреда = 'дробящий':
		if хрупкий[$враг[текущий]] = 1: здоровье_врага[текущий] -= нанесенный_вред
		if безустали[$враг[текущий]] = 0: выносливость_врага[текущий] -= нанесенный_вред
		if бесстрашный[$враг[текущий]] = 0: дух_врага[текущий] -= нанесенный_вред
		дух_игрока += нанесенный_вред/2
	else
		if бессмертный[$враг[текущий]] = 0: здоровье_врага[текущий] -= нанесенный_вред
		if безустали[$враг[текущий]] = 0: выносливость_врага[текущий] -= нанесенный_вред
		if бесстрашный[$враг[текущий]] = 0: дух_врага[текущий] -= нанесенный_вред
		дух_игрока += нанесенный_вред/2
	end
end

if $наложение = 'слабость':
	if слабость[текущий] <= длительность: слабость[текущий] = длительность
	if слабость[текущий] > длительность: слабость[текущий] += 1
end
if $наложение = 'скованность':
	if скованность[текущий] <= длительность: скованность[текущий] = длительность
	if скованность[текущий] > длительность: скованность[текущий] += 1
end
if $наложение = 'боль':
	if боль[текущий] <= длительность[i]: боль[текущий] = длительность
	if боль[текущий] > длительность[i]: боль[текущий] += 1
end
if $наложение = 'шаткость':
	if шаткость[текущий] <= длительность: шаткость[текущий] = длительность
	if шаткость[текущий] > длительность: шаткость[текущий] += 1
end
if $наложение = 'ошеломление':
	if ошеломление[текущий] <= длительность: ошеломление[текущий] = длительность
	if ошеломление[текущий] > длительность: ошеломление[текущий] += 1
end
if $наложение = 'рассеянность':
	if рассеянность[текущий] <= длительность: рассеянность[текущий] = длительность
	if рассеянность[текущий] > длительность: рассеянность[текущий] += 1
end
if $наложение = 'бешенство':
	if бешенство <= длительность: бешенство = длительность
	if бешенство > длительность: бешенство += 1
end
if $наложение = 'разгон':
	if разгон <= длительность: разгон = длительность
	if разгон > длительность: разгон += 1
end
if $наложение = 'меткость':
	if меткость <= длительность: меткость = длительность
	if меткость > длительность: меткость += 1
end
if $наложение = 'адреналин':
	if адреналин <= длительность: адреналин = длительность
	if адреналин > длительность: адреналин += 1
end
if $наложение = 'верткость':
	if верткость <= длительность: верткость = длительность
	if верткость > длительность: верткость += 1
end
if $наложение = 'внимание':
	if внимание <= длительность: внимание = длительность
	if внимание > длительность: внимание += 1
end

if это_суперудар = 1: dynamic $спецэффект_суперудара[$суперудар[супер]]
это_суперудар = 0

i = 0
:loop1
if i < количество_врагов:
	i += 1
	!Вред
	if враг[i] = 1:
		if $тип_нанесенного_вреда[i] = 'психический':
			дух_игрока -= cheat_fight_dif * нанесенный_вред[i]
			дух_врага[i] += нанесенный_вред[i]/2
			jump 'loop2'
		end
		if $тип_нанесенного_вреда[i] = 'дробящий':
			выносливость_игрока -= cheat_fight_dif * нанесенный_вред[i]
			дух_игрока -= cheat_fight_dif * нанесенный_вред[i]
			дух_врага[i] += нанесенный_вред[i]/2
			jump 'loop2'
		end
		!Vatican Champion damage bug fix/hack - crushboss (disabled by ImperatorAugustus)
		!if challenge_type = 1 and $ge = 'champion_vatican' and нанесенный_вред[i] > 36:
		!	нанесенный_вред[i] = rand(10,24)
		!end
		здоровье_игрока -= cheat_fight_dif * нанесенный_вред[i]
		&! master wearing chimera gem recovers 3-16 health after every hit (amount derived from master_supermacy, excluding allure, charisma and slave-specific factors)
		if chimera_gem_on = 1: здоровье_игрока = min(макс_здоровье_игрока, здоровье_игрока + min(нанесенный_вред[i], master_domination + master_str + magna_magnifika + item_supermacy_bonus)) &! healing is capped by max health and by amount of damage received
		выносливость_игрока -= cheat_fight_dif * нанесенный_вред[i]
		дух_игрока -= cheat_fight_dif * нанесенный_вред[i]
		дух_врага[i] += нанесенный_вред[i]/2
		:loop2
		!statuses
		if $наложение[i] = 'слабость':
			if слабость[0] <= длительность[i]: слабость[0] = длительность[i]
			if слабость[0] > длительность[i]: слабость[0] += 1
		end
		if $наложение[i] = 'скованность':
			if скованность[0] <= длительность[i]: скованность[0] = длительность[i]
			if скованность[0] > длительность[i]: скованность[0] += 1
		end
		if $наложение[i] = 'боль':
			if боль[0] <= длительность[i]: боль[0] = длительность[i]
			if боль[0] > длительность[i]: боль[0] += 1
		end
		if $наложение[i] = 'шаткость':
			if шаткость[0] <= длительность[i]: шаткость[0] = длительность[i]
			if шаткость[0] > длительность[i]: шаткость[0] += 1
		end
		if $наложение[i] = 'ошеломление':
			if ошеломление[0] <= длительность[i]: ошеломление[0] = длительность[i]
			if ошеломление[0] > длительность[i]: ошеломление[0] += 1
		end
		if $наложение[i] = 'рассеянность':
			if рассеянность[0] <= длительность[i]: рассеянность[0] = длительность[i]
			if рассеянность[0] > длительность[i]: рассеянность[0] += 1
		end
		if $наложение[i] = 'бешенство':
			if бешенство[i] <= длительность[i]: бешенство[i] = длительность[i]
			if бешенство[i] > длительность[i]: бешенство[i] += 1
		end
		if $наложение[i] = 'разгон':
			if разгон[i] <= длительность[i]: разгон[i] = длительность[i]
			if разгон[i] > длительность[i]: разгон[i] += 1
		end
		if $наложение[i] = 'меткость':
			if меткость[i] <= длительность[i]: меткость[i] = длительность[i]
			if меткость[i] > длительность[i]: меткость[i] += 1
		end
		if $наложение[i] = 'адреналин':
			if адреналин[i] <= длительность[i]: адреналин[i] = длительность[i]
			if адреналин[i] > длительность[i]: адреналин[i] += 1
		end
		if $наложение[i] = 'верткость':
			if верткость[i] <= длительность[i]: верткость[i] = длительность[i]
			if верткость[i] > длительность[i]: верткость[i] += 1
		end
		if $наложение[i] = 'внимание':
			if внимание[i] <= длительность[i]: внимание[i] = длительность[i]
			if внимание[i] > длительность[i]: внимание[i] += 1
		end
	end
	jump "loop1"
end

!check for enemy death
i = 0
:loop5
if i < количество_врагов:
	i += 1
	if враг[i] = 1:
		if здоровье_врага[i] <= 0 and $класс_врага[i]!'пешка':
			враг[i] = 0
			поверженные_враги += 1
			$трофей[тр] = $труп_моба_в_локацию[$враг[i]]
			труп[$враг[i]] += 1
			тр += 1
			$действия_врага[i] = '<<$труп_врага[i]>>
'
			jump 'loop5'
		end
		if выносливость_врага[i] <= 0 and $класс_врага[i]!'пешка':
			враг[i] = 0
			поверженные_враги += 1
			$трофей[тр] = $вырубленный_моб_в_локацию[$враг[i]]
			в_отключке[$враг[i]] += 1
			тр += 1
			$действия_врага[i] = '<<$тело_врага[i]>>
'
			jump 'loop5'
		end
		if дух_врага[i] <= 0 and $класс_врага[i]!'пешка':
			враг[i] = 0
			поверженные_враги += 1
			$действия_врага[i] = '<<$беглец[i]>>
'
			jump 'loop5'
		end
		if $состояние[i] = 'повержен':
			враг[i] = 0
			поверженные_враги += 1
			$трофей[тр] = $труп_моба_в_локацию[$враг[i]]
			труп[$враг[i]] += 1
			тр += 1
			$действия_врага[i] = '<<$труп_врага[i]>>
'
		end
	end
	jump 'loop5'
end

killvar 'нанесенный_вред'

!check for fight end
if поверженные_враги = количество_врагов:
	$итог_боя = 'победа'
	!fixed, otherwise after a battle with one opponent the final spirit will always be equal to 5
	if количество_врагов > 2: дух_игрока = 5*количество_врагов
	gt 'конец_боя'
end
if здоровье_игрока <= 0:
	$итог_боя = 'убит'
	gt 'конец_боя'
end
if выносливость_игрока <= 0:
	$итог_боя = 'вырубился'
	gt 'конец_боя'
end
if дух_игрока <= 0:
	$итог_боя = 'бегство'
	gt 'конец_боя'
end

gs 'боевое_меню'
gt 'боевой_интерфейс'

--- конец_раунда ---------------------------------

repo_name: Sutopia/game

license: unknown


code:
# начать_бой
!BATTLE BEGINS IN THIS LOCATION
!Overhauled by crushboss
!expects combatant to be set to 0, 1 or 2 before calling this to select the defender (master, slave, assistant respectively)

!TAKE OUT THE WEAPONS

if get_weapon = 0:
	$memplace = $place
	get_weapon = 1
	memcf = colosseum_fight
	colosseum_fight = 0
	$оружие = ''
	$вторичный = ''
	interaction_city = 901
	if surprise_attack = 1: interaction_city = 902
	if slave_attack = 1: interaction_city = 903
	gt 'interaction_city'
else
	!Assign primary and secondary weapons - crushboss
	dynamic $primary_weapon
	dynamic $secondary_weapon
	if a = 1: dynamic $previous_weapon
	colosseum_fight = memcf
	get_weapon = 2
	surprise_attack = 0
end

!Fix blank screen bug - crushboss
if slave_state ! CONST_INT['no_slave'] and combatant = 1:
	if $slave['wpn'] = '': $slave['wpn'] = 'безоружный'
	if $slave['armor'] = '': $slave['armor'] = 'без_брони'
	if $slave['cloth'] = '': $slave['cloth'] = 'голая'
end

!Fix blank screen bug - crushboss
if assistant_state ! CONST_INT['no_slave'] and combatant = 2:
	if $assistant['wpn'] = '': $assistant['wpn'] = 'безоружный'
	if $assistant['armor'] = '': $assistant['armor'] = 'без_брони'
	if $assistant['cloth'] = '': $assistant['cloth'] = 'голая'
end

!resetting vars
a = 0
nogoto = 0
поверженные_враги = 0

killvar 'no_wpn'
killvar '$состояние'

killvar 'слабость'
killvar 'скованность'
killvar 'боль'
killvar 'шаткость'
killvar 'ошеломление'
killvar 'рассеянность'
killvar 'бешенство'
killvar 'разгон'
killvar 'меткость'
killvar 'адреналин'
killvar 'верткость'
killvar 'внимание'

killvar 'суперудар'
killvar 'наложение'
killvar '$боевая_обстановка'
killvar '$действия_игрока'
killvar '$действия_врага'

!ui
gs 'раскладка_бой'

!Set master/slaver stats - start
base_str = master_str
base_flagelation = master_flagelation
сила = master_fighter
ловкость = master_fighter
восприятие = master_fighter

!Load Combat Databases
gs '#тексты_движка'
gs '#противники'
gs '#суперудары'
gs '#боевые_предметы'
gs '#dynamic'

$combatant_ava = $master_ava_color
$combatant_name = $master_name
$броня = $master_armor

if slave_attack = 1:
	$за_спиной = ''
	$слева = ''
	$справа = ''
	$предплечье = ''
	$в_сапоге = ''
	$броня = 'без_брони'
end

&! S+ health: loli = 40, young = 50, mature = 60, master = 70
&! master wearing chimera gem recovers 3-16 health after every hit (amount derived from master_supermacy, excluding allure, charisma and slave-specific factors)

макс_здоровье_игрока = master_str * 14 - master_wounds_rate
if макс_здоровье_игрока < 1: макс_здоровье_игрока = 1
здоровье_игрока = макс_здоровье_игрока
макс_выносливость_игрока = 50 + (master_energy*5)
if bull_ring_on = 1: макс_выносливость_игрока *= 2
выносливость_игрока = макс_выносливость_игрока
норм_дух_игрока = master_cha*5 + master_domination*5 + master_fighter*10
if snake_amulet_on = 1: норм_дух_игрока *= 2
дух_игрока = норм_дух_игрока
сила_передышки = 10

copyarr '$суперудар', '$master_spm'
!End of master/slaver stats

if combatant = 1:
	$combatant_ava = '<<$slave[''ava'']>>.png'
	$combatant_name = $slave_name
	$броня = $slave['armor']

	макс_здоровье_игрока = slave['stamina'] * 10 - slave_rate['wounds']
	if slave['gladiatrix_affinity'] > 0: макс_здоровье_игрока = slave['stamina']*10
	if slave['age'] = CONST_INT['loli_age']: макс_здоровье_игрока -= макс_здоровье_игрока/5
	if slave['age'] = CONST_INT['milf_age']: макс_здоровье_игрока += slave['stamina']*2
	if макс_здоровье_игрока < 1: макс_здоровье_игрока = 1
	здоровье_игрока = макс_здоровье_игрока
	макс_выносливость_игрока = 50 + (slave['energy']*5)
	if slave['gladiatrix_affinity'] > 0: макс_выносливость_игрока = 75 + (slave['energy']*5)
	if slave['age'] = CONST_INT['loli_age']: макс_выносливость_игрока -= макс_выносливость_игрока/3
	выносливость_игрока = макс_выносливость_игрока
	норм_дух_игрока = slave['ego']*10 + slave['gladiatrix']*10
	if slave['gladiatrix_affinity'] > 0: норм_дух_игрока += slave['ego']*10
	дух_игрока = норм_дух_игрока
	сила_передышки = 10
	slave['calories'] -= 5
	slave_rate['hygiene'] += 40
	slave_rate['sensitivity'] -= 5

	base_str = slave['stamina'] + slave['gladiatrix_affinity']
	if slave['age'] = CONST_INT['loli_age']: base_str = (2*base_str)/3 + slave['gladiatrix_affinity']
	if slave['age'] = CONST_INT['milf_age']: base_str += 1
	base_flagelation = slave['gladiatrix'] + slave['gladiatrix_affinity']
	сила = slave['gladiatrix'] + slave['gladiatrix_affinity']
	ловкость = slave['gladiatrix'] + slave['gladiatrix_affinity']
	восприятие = slave['gladiatrix'] + slave['gladiatrix_affinity']
	if slave['gladiatrix_affinity_revealed'] = 0: slave['gladiatrix_affinity_revealed'] = 1
	killvar '$суперудар'
end

if combatant = 2:
	$combatant_ava = '<<$assistant[''ava'']>>.png'
	$combatant_name = $assistant_name
	$броня = $assistant['armor']

	макс_здоровье_игрока = assistant['stamina'] * 10 - assistant_rate['wounds']
	if assistant['gladiatrix_affinity'] > 0: макс_здоровье_игрока = assistant['stamina']*10
	if assistant['age'] = CONST_INT['loli_age']: макс_здоровье_игрока -= макс_здоровье_игрока/5
	if assistant['age'] = CONST_INT['milf_age']: макс_здоровье_игрока += assistant['stamina']*2
	if макс_здоровье_игрока < 1: макс_здоровье_игрока = 1
	здоровье_игрока = макс_здоровье_игрока
	макс_выносливость_игрока = 50 + (assistant['energy']*5)
	if assistant['gladiatrix_affinity'] > 0: макс_выносливость_игрока = 75 + (assistant['energy']*5)
	if assistant['age'] = CONST_INT['loli_age']: макс_выносливость_игрока -= макс_выносливость_игрока/3
	выносливость_игрока = макс_выносливость_игрока
	норм_дух_игрока = assistant['ego']*10 + assistant['gladiatrix']*10
	if assistant['gladiatrix_affinity'] > 0: норм_дух_игрока += assistant['ego']*10
	дух_игрока = норм_дух_игрока
	сила_передышки = 10
	assistant['calories'] -= 5
	assistant_rate['hygiene'] += 40
	assistant_rate['sensitivity'] -= 5

	base_str = assistant['stamina'] + assistant['gladiatrix_affinity']
	if assistant['age'] = CONST_INT['loli_age']: base_str = (2*base_str)/3 + assistant['gladiatrix_affinity']
	if assistant['age'] = CONST_INT['milf_age']: base_str += 1
	base_flagelation = assistant['gladiatrix'] + assistant['gladiatrix_affinity']
	сила = assistant['gladiatrix'] + assistant['gladiatrix_affinity']
	ловкость = assistant['gladiatrix'] + assistant['gladiatrix_affinity']
	восприятие = assistant['gladiatrix'] + assistant['gladiatrix_affinity']
	killvar '$суперудар'
end

$ключевые_условия = 'нет'
$ключевые_условия += $ключевое_слово_1[$оружие]
$ключевые_условия += $ключевое_слово_2[$оружие]
$ключевые_условия += $ключевое_слово_3[$оружие]
$ключевые_условия += $ключевое_слово_4[$оружие]
$ключевые_условия += $ключевое_слово_5[$оружие]
$ключевые_условия += $ключевое_слово_1[$броня]
$ключевые_условия += $ключевое_слово_2[$броня]
$ключевые_условия += $ключевое_слово_3[$броня]
$ключевые_условия += $ключевое_слово_4[$броня]
$ключевые_условия += $ключевое_слово_5[$броня]
$ключевые_условия += $ключевое_слово_1[$вторичный]
$ключевые_условия += $ключевое_слово_2[$вторичный]
$ключевые_условия += $ключевое_слово_3[$вторичный]
$ключевые_условия += $ключевое_слово_4[$вторичный]
$ключевые_условия += $ключевое_слово_5[$вторичный]

dynamic $броня_надеть[$броня]
dynamic $броня_эффект[$броня]

if $враг[1] = 'воспитуемая':

	slave_base_dmg = slave['gladiatrix']
	$slave_dmg_type = 'дробящий'

	if $slave['left_wpn'] = 'глушилка' or $slave['right_wpn'] = 'глушилка': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['left_wpn'] = 'кастет' or $slave['right_wpn'] = 'кастет': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['left_wpn'] = 'кинжал' or $slave['right_wpn'] = 'кинжал': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['left_wpn'] = 'стилет' or $slave['right_wpn'] = 'стилет': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['left_wpn'] = 'нагайка' or $slave['right_wpn'] = 'нагайка': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'психический'
	if $slave['left_wpn'] = 'тесак' or $slave['right_wpn'] = 'тесак': slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'

	if $slave['back_wpn'] = 'кнут' or $slave['left_wpn'] = 'кнут' or $slave['right_wpn'] = 'кнут': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'психический'
	if $slave['back_wpn'] = 'демократизатор' or $slave['left_wpn'] = 'демократизатор' or $slave['right_wpn'] = 'демократизатор': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['back_wpn'] = 'мулава' or $slave['left_wpn'] = 'мулава' or $slave['right_wpn'] = 'мулава': slave_base_dmg = 4+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['back_wpn'] = 'шпага' or $slave['left_wpn'] = 'шпага' or $slave['right_wpn'] = 'шпага': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'рапира' or $slave['left_wpn'] = 'рапира' or $slave['right_wpn'] = 'рапира': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'кончар' or $slave['left_wpn'] = 'кончар' or $slave['right_wpn'] = 'кончар': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'гладиус' or $slave['left_wpn'] = 'гладиус' or $slave['right_wpn'] = 'гладиус': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'трезубец' or $slave['left_wpn'] = 'трезубец' or $slave['right_wpn'] = 'трезубец': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'бастард' or $slave['left_wpn'] = 'бастард' or $slave['right_wpn'] = 'бастард': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'
	if $slave['back_wpn'] = 'мачете' or $slave['left_wpn'] = 'мачете' or $slave['right_wpn'] = 'мачете': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'
	if $slave['back_wpn'] = 'катана' or $slave['left_wpn'] = 'катана' or $slave['right_wpn'] = 'катана': slave_base_dmg = 3+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'

	if $slave['back_wpn'] = 'бита': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['back_wpn'] = 'скотобой': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'психический'
	if $slave['back_wpn'] = 'фламберг': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'
	if $slave['back_wpn'] = 'нагината': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
	if $slave['back_wpn'] = 'моргенштерн': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'дробящий'
	if $slave['back_wpn'] = 'грейтекс': slave_base_dmg = 5+slave['gladiatrix'] & $slave_dmg_type = 'рубящий'

	if slave_attack = 1:
		slave_base_dmg = 1+slave['gladiatrix'] & $slave_dmg_type = 'колющий'
		slave_attack = 0
	end

	$название_моба['воспитуемая'] = 'Slave'
	$аватара_моба['воспитуемая'] = '<<$seed_ava_clear[slave_type]>>.png'
	$описание_моба['воспитуемая'] = 'This is your slave.'
	$склонение_моб['воспитуемая'] = 'a slave'
	$склонение_моба['воспитуемая'] = 'a slave'
	$склонение_мобу['воспитуемая'] = 'a slave'
	$класс_моба['воспитуемая'] = 'элитный'
	базовое_здоровье['воспитуемая'] = slave['stamina'] * 10 - slave_rate['wounds']
	if базовое_здоровье['воспитуемая'] < 1: базовое_здоровье['воспитуемая'] = 1
	базовая_выносливость['воспитуемая'] = 50 + (slave['energy']*5)
	чек = базовое_здоровье['воспитуемая'] * 2
	if базовая_выносливость['воспитуемая'] > чек: базовая_выносливость['воспитуемая'] = чек
	базовый_дух['воспитуемая'] = slave['ego'] * 10
	$интеллект['воспитуемая'] = 'искусственный_идиот'

	базовый_вред['воспитуемая'] = slave_base_dmg
	$атака_1_тип['воспитуемая'] = 'точная'
	$атака_1_тип_вреда['воспитуемая'] = $slave_dmg_type
	$атака_1_штраф['воспитуемая'] = 'боль'
	$атака_1_бонус['воспитуемая'] = 'верткость'
	атака_1_длительность['воспитуемая'] = 1 + slave['gladiatrix']
	$атака_1_текст['воспитуемая'] = '<<$slave_name>> hits you right in the groin' + iif(slave_base_dmg > slave['gladiatrix'], ' with her weapon', '')
	$атака_2_тип['воспитуемая'] = 'быстрая'
	$атака_2_тип_вреда['воспитуемая'] = $slave_dmg_type
	$атака_2_штраф['воспитуемая'] = 'боль'
	$атака_2_бонус['воспитуемая'] = 'бешенство'
	атака_2_длительность['воспитуемая'] = 1 + slave['gladiatrix']
	$атака_2_текст['воспитуемая'] = '<<$slave_name>> frenziedly showers you with strikes' + iif(slave_base_dmg > slave['gladiatrix'], ' with her weapon', '')
	$атака_3_тип['воспитуемая'] = 'сильная'
	$атака_3_тип_вреда['воспитуемая'] = $slave_dmg_type
	$атака_3_штраф['воспитуемая'] = 'боль'
	$атака_3_бонус['воспитуемая'] = 'адреналин'
	атака_3_длительность['воспитуемая'] =  1 + slave['gladiatrix']
	$атака_3_текст['воспитуемая'] = '<<$slave_name>> hits you with all of her strength' + iif(slave_base_dmg > slave['gladiatrix'], ' with her weapon', '')

	$смерть['воспитуемая'] = '<<$slave_name>> lying on the floor lifeless. Last blow was fatal for her.'
	$отключка['воспитуемая'] = '<<$slave_name>> lying unconscious.'
	$бегство['воспитуемая'] = '<<$slave_name>> is not ready to continue the fight. She gives up…'

	хрупкий['воспитуемая'] = 0
	тонкое_тело['воспитуемая'] = 0
	бессмертный['воспитуемая'] = 0
	безустали['воспитуемая'] = 0
	бесстрашный['воспитуемая'] = 0

	модификатор_колющий['воспитуемая'] = 0
	модификатор_рубящий['воспитуемая'] = 0
	модификатор_дробящий['воспитуемая'] = 0
	модификатор_огонь['воспитуемая'] = 0
	модификатор_холод['воспитуемая'] = 0
	модификатор_молния['воспитуемая'] = 0
	модификатор_свет['воспитуемая'] = 0
	модификатор_тьма['воспитуемая'] = 0
	модификатор_серебро['воспитуемая'] = 0
	модификатор_холодное_железо['воспитуемая'] = 0
	модификатор_психический['воспитуемая'] = 0

	if $slave['armor'] = 'комбез':
		модификатор_колющий['воспитуемая'] -= 1
		модификатор_рубящий['воспитуемая'] -= 1
		модификатор_дробящий['воспитуемая'] -= 1
		модификатор_холод['воспитуемая'] -= 1
		модификатор_молния['воспитуемая'] -= 1
		модификатор_огонь['воспитуемая'] -= 1
	end

	if $slave['armor'] = 'кожан':
		модификатор_колющий['воспитуемая'] -= 3
		модификатор_рубящий['воспитуемая'] -= 2
		модификатор_дробящий['воспитуемая'] -= 2
		модификатор_холод['воспитуемая'] -= 3
		модификатор_молния['воспитуемая'] -= 4
		модификатор_огонь['воспитуемая'] -= 5
	end

	if $slave['armor'] = 'эльчуга':
		модификатор_колющий['воспитуемая'] -= 2
		модификатор_рубящий['воспитуемая'] -= 4
		модификатор_холод['воспитуемая'] += 2
		модификатор_молния['воспитуемая'] += 2
		модификатор_огонь['воспитуемая'] += 2
	end

	if $slave['armor'] = 'ячуга':
		модификатор_колющий['воспитуемая'] -= 4
		модификатор_рубящий['воспитуемая'] -= 5
		модификатор_дробящий['воспитуемая'] -= 1
		модификатор_холод['воспитуемая'] += 1
		модификатор_огонь['воспитуемая'] += 2
		модификатор_молния['воспитуемая'] += 1
	end

	if $slave['armor'] = 'полудоспех':
		модификатор_колющий['воспитуемая'] -= 4
		модификатор_рубящий['воспитуемая'] -= 4
		модификатор_дробящий['воспитуемая'] -= 3
		модификатор_холод['воспитуемая'] += 1
		модификатор_огонь['воспитуемая'] += 1
		модификатор_молния['воспитуемая'] += 1
	end

	if $slave['armor'] = 'плейт':
		модификатор_колющий['воспитуемая'] -= 5
		модификатор_рубящий['воспитуемая'] -= 5
		модификатор_дробящий['воспитуемая'] -= 5
		модификатор_холод['воспитуемая'] += 5
		модификатор_огонь['воспитуемая'] += 5
		модификатор_молния['воспитуемая'] += 5
	end

	if $slave['armor'] = 'кольчуга':
		модификатор_колющий['воспитуемая'] -= 10
		модификатор_рубящий['воспитуемая'] -= 10
		модификатор_дробящий['воспитуемая'] -= 10
		модификатор_холод['воспитуемая'] -= 10
		модификатор_огонь['воспитуемая'] -= 10
		модификатор_молния['воспитуемая'] -= 10
		модификатор_свет['воспитуемая'] -= 10
		модификатор_тьма['воспитуемая'] -= 10
		модификатор_серебро['воспитуемая'] -= 10
		модификатор_холодное_железо['воспитуемая'] -= 10
	end
end

!Getting information about mobs/enemies with a cycle
i = 0
:loop
if i < количество_врагов:
	i += 1
	$имя_врага[i] = $название_моба[$враг[i]]
	$склонение_врага[i] = $склонение_моба[$враг[i]]
	$класс_врага[i] = $класс_моба[$враг[i]]
	$труп_врага[i] = $смерть[$враг[i]]
	$тело_врага[i] = $отключка[$враг[i]]
	$беглец[i] = $бегство[$враг[i]]

	макс_здоровье_врага[i] = базовое_здоровье[$враг[i]]
	здоровье_врага[i] = базовое_здоровье[$враг[i]]
	выносливость_врага[i] = базовая_выносливость[$враг[i]]
	дух_врага[i] = базовый_дух[$враг[i]]
	вред_врага[i] = базовый_вред[$враг[i]]
	случай = 1 + ((48271 * (day + master_energy + sparks)) mod 65537)/(65537/3) &! pseudo-rand(1,3)
	if случай = 1: $защита[i] = 'блок'
	if случай = 2: $защита[i] = 'контратака'
	if случай = 3: $защита[i] = 'уклонение'
	враг[i] = 1
	jump 'loop'
end

текущий = 1

gs 'боевое_меню'
gt 'боевой_интерфейс'

--- начать_бой ---------------------------------


code:
# передышка
!GOTO HERE IF PLAYER CHOOSES "DEFEND" OPTION

!Player gets rid of all the harmful conditions
слабость = 0
скованность = 0
боль = 0
шаткость = 0
ошеломление = 0
рассеянность = 0

!Player restores some stamina
выносливость_игрока += сила_передышки
if выносливость_игрока > макс_выносливость_игрока: выносливость_игрока = макс_выносливость_игрока

$действия_игрока = 'You go on the defensive [harmful status removed] [stamina +<<сила_передышки>>]'

gt 'ход_противников'

--- передышка ---------------------------------


code:
# раскладка_бой
!FIGHT UI
CLOSE ALL
if ui_style = 1:$backimage = 'content/pic/ui/old/bg_fight_old.png'
if ui_style = 2:$backimage = 'content/pic/ui/grimdark/bg_fight.png'
if ui_style = 0:$backimage = 'content/pic/ui/classic/bg_fight.png'

MSG_X = 350
--- раскладка_бой ---------------------------------


code:
# рассчет_вреда
!CALCULATION OF DAMAGE FROM ALL MODIFIERS
модификатор = 0

!Interaction of the type of protection and attack
$эффект = 'удвоение'
if $защита[def] = 'блок' and $атака[atk] = 'сильная': модификатор += 1
if $защита[def] = 'уклонение' and $атака[atk] = 'быстрая': модификатор += 1
if $защита[def] = 'контратака' and $атака[atk] = 'точная': модификатор += 1

if $защита[def] = 'блок' and $атака[atk] = 'точная': $эффект = 'бонус'
if $защита[def] = 'уклонение' and $атака[atk] = 'сильная': $эффект = 'бонус'
if $защита[def] = 'контратака' and $атака[atk] = 'быстрая': $эффект = 'бонус'

if $защита[def] = 'блок' and $атака[atk] = 'быстрая': $эффект = 'штраф'
if $защита[def] = 'уклонение' and $атака[atk] = 'точная': $эффект = 'штраф'
if $защита[def] = 'контратака' and $атака[atk] = 'сильная': $эффект = 'штраф'

!taking statuses into account
if $атака[atk] = 'сильная':
	if бешенство[atk] > 0: модификатор += 1
	if шаткость[def] > 0: модификатор += 1
	if слабость[atk] > 0: модификатор -= 1
	if адреналин[def] > 0: модификатор -= 1
end

if $атака[atk] = 'быстрая':
	if разгон[atk] > 0: модификатор += 1
	if ошеломление[def] > 0: модификатор += 1
	if скованность[atk] > 0: модификатор -= 1
	if верткость[def] > 0: модификатор -= 1
end

if $атака[atk] = 'точная':
	if меткость[atk] > 0: модификатор += 1
	if рассеянность[def] > 0: модификатор += 1
	if боль[atk] > 0: модификатор -= 1
	if внимание[def] > 0: модификатор -= 1
end

!damage calculation itself
if модификатор < -2: нанесенный_вред[atk] = вред_на_рассчет/6
if модификатор = -2: нанесенный_вред[atk] = вред_на_рассчет/4
if модификатор = -1: нанесенный_вред[atk] = вред_на_рассчет/2
if модификатор = 0: нанесенный_вред[atk] = вред_на_рассчет
if модификатор = 1: нанесенный_вред[atk] = вред_на_рассчет*2
if модификатор = 2: нанесенный_вред[atk] = вред_на_рассчет*4
if модификатор > 2: нанесенный_вред[atk] = вред_на_рассчет*6

модифер = 0

if def = 0: dynamic 'модифер = модификатор_<<$рассчетный_тип_вреда>>'
if def > 0: dynamic 'модифер = модификатор_<<$рассчетный_тип_вреда>>[$враг[def]]'
нанесенный_вред[atk] += модифер

if нанесенный_вред[atk] < 1:
	нанесенный_вред[atk] = 1
	a = rand(1,10)
	if a = 1: нанесенный_вред[atk] += 1
	if a = 2: нанесенный_вред[atk] += 2
	if a = 3: нанесенный_вред[atk] += 3
	a = 0
end

$тип_нанесенного_вреда[atk] = $рассчетный_тип_вреда

--- рассчет_вреда ---------------------------------


code:
# сменить_оружие
!CHANGING WEAPONS

!creating menu
$боевое_меню = ''
$боевое_меню += "Change primary
"
$боевое_меню += "Change secondary
"
$боевое_меню += "Remove primary
"
$боевое_меню += "Remove secondary
"
$боевое_меню += "
"
$боевое_меню += "Back
"

gt 'боевой_интерфейс'
--- сменить_оружие ---------------------------------


code:
# сменить_оружие_вторичное
!creating menu - secondary weapon change
$боевое_меню = ''
if $за_спиной!'':$боевое_меню += "Shoulder Holster:<<$item_name[$за_спиной]>>
"
if $слева!'':$боевое_меню += "Left Hand:<<$item_name[$слева]>>
"
if $справа!'':$боевое_меню += "Right Hand:<<$item_name[$справа]>>
"
if $предплечье!'' and combatant = 0:$боевое_меню += "Sleeve Holster:<<$item_name[$предплечье]>>
"
if $в_сапоге!'' and combatant = 0:$боевое_меню += "Boot Holster:<<$item_name[$в_сапоге]>>
"
$боевое_меню += "
"
$боевое_меню += "Back
"

gt 'боевой_интерфейс'
--- сменить_оружие_вторичное ---------------------------------

path: game/locations/сменить_оружие_вторичное.qsrc


code:
# сменить_оружие_основное
!creating menu - primary weapon change
$боевое_меню = ''
if $за_спиной!'':$боевое_меню += "Shoulder Holster:<<$item_name[$за_спиной]>>
"
if $слева!'':$боевое_меню += "Left Hand:<<$item_name[$слева]>>
"
if $справа!'':$боевое_меню += "Right Hand:<<$item_name[$справа]>>
"
if $предплечье!'' and combatant = 0:$боевое_меню += "Sleeve Holster:<<$item_name[$предплечье]>>
"
if $в_сапоге!'' and combatant = 0:$боевое_меню += "Boot Holster:<<$item_name[$в_сапоге]>>
"
$боевое_меню += "
"
$боевое_меню += "Back
"

gt 'боевой_интерфейс'

--- сменить_оружие_основное ---------------------------------

path: game/locations/сменить_оружие_основное.qsrc


code:
# суперудары
!SUPERB SELECTION MENU
!Overhauled by crushboss

!Reset vars - crushboss
killvar '$меню_суперудар'
killvar '$боевое_меню'
killvar 'вред_оружия_игрока'
killvar '$тип_вреда_оружия'

$меню_суперудар[1] = ''
$меню_суперудар[2] = ''
$меню_суперудар[3] = ''
$меню_суперудар[4] = ''
$меню_суперудар[5] = ''
$меню_суперудар[6] = ''
$меню_суперудар[7] = ''
$меню_суперудар[8] = ''
$боевое_меню = ''
вред_оружия_игрока = 0
$тип_вреда_оружия = ''

!Obtain information about the player’s current weapon
вред_оружия_игрока = базовый_вред[$оружие]
$тип_вреда_оружия = $тип_вреда[$оружие]

!Build list of learned special techniques that match the weapon type - crushboss

!Roundhouse Kick - ALL
if spm_learned['удар_с_разворота'] = 1 and суперудар_сделан[11] = 0:
	$суперудар_название[$суперудар[1]] = "Roundhouse Kick"
	$меню_суперудар[1] = $суперудар_название[$суперудар[1]]
	! $меню_суперудар[1] = 'Roundhouse Kick'
else
	$меню_суперудар[1] = ''
end

!Swift Blow - Slashing weapons - рубящий
if spm_learned['рассечение'] = 1 and суперудар_сделан[12] = 0 and $тип_вреда_оружия = 'рубящий':
	$суперудар_название[$суперудар[2]] = "Swift Blow"
	$меню_суперудар[2] = $суперудар_название[$суперудар[2]]
	! $меню_суперудар[2] = 'Swift Blow'
else
	$меню_суперудар[2] = ''
end

!Battle Cry - ALL
if spm_learned['воинственный_клич'] = 1 and суперудар_сделан[13] = 0:
	$суперудар_название[$суперудар[3]] = "Battle Cry"
	$меню_суперудар[3] = $суперудар_название[$суперудар[3]]
	! $меню_суперудар[3] = 'Battle Cry'
else
	$меню_суперудар[3] = ''
end

!Heavy Blow - Blunt weapons - дробящий
if spm_learned['оглушение'] = 1 and суперудар_сделан[14] = 0 and $тип_вреда_оружия = 'дробящий':
	$суперудар_название[$суперудар[4]] = "Heavy Blow"
	$меню_суперудар[4] = $суперудар_название[$суперудар[4]]
	! $меню_суперудар[4] = 'Heavy Blow'
else
	$меню_суперудар[4] = ''
end

!Precise Hit - Piercing weapons - колющий
if spm_learned['ослепление'] = 1 and суперудар_сделан[15] = 0 and $тип_вреда_оружия = 'колющий':
	$суперудар_название[$суперудар[5]] = "Precise Hit"
	$меню_суперудар[5] = $суперудар_название[$суперудар[5]]
	! $меню_суперудар[5] = 'Precise Hit'
else
	$меню_суперудар[5] = ''
end

!Dashing Blow - Slashing weapons - рубящий
if spm_learned['подрезка'] = 1 and суперудар_сделан[16] = 0 and $тип_вреда_оружия = 'рубящий':
	$суперудар_название[$суперудар[6]] = "Dashing Blow"
	$меню_суперудар[6] = $суперудар_название[$суперудар[6]]
	! $меню_суперудар[6] = 'Dashing Blow'
else
	$меню_суперудар[6] = ''
end

!Riposte - piercing weapons - колющий
if spm_learned['ответный_удар'] = 1 and суперудар_сделан[17] = 0 and $тип_вреда_оружия = 'колющий':
	$суперудар_название[$суперудар[7]] = "Riposte"
	$меню_суперудар[7] = $суперудар_название[$суперудар[7]]
	! $меню_суперудар[7] = 'Riposte'
else
	$меню_суперудар[7] = ''
end

!Face Bash - Blunt weapons - дробящий
if spm_learned['лицо_прикладом'] = 1 and суперудар_сделан[18] = 0 and $тип_вреда_оружия = 'дробящий':
	$суперудар_название[$суперудар[8]] = "Face Bash"
	$меню_суперудар[8] = $суперудар_название[$суперудар[8]]
	! $меню_суперудар[8] = 'Face Bash'
else
	$меню_суперудар[8] = ''
end

!creating menu
killvar '$боевое_меню'
$боевое_меню = "
"
if $меню_суперудар[1] ! '': $боевое_меню += "<<$меню_суперудар[1]>>
"
if $меню_суперудар[2] ! '': $боевое_меню += "<<$меню_суперудар[2]>>
"
if $меню_суперудар[3] ! '': $боевое_меню += "<<$меню_суперудар[3]>>
"
if $меню_суперудар[4] ! '': $боевое_меню += "<<$меню_суперудар[4]>>
"
if $меню_суперудар[5] ! '': $боевое_меню += "<<$меню_суперудар[5]>>
"
if $меню_суперудар[6] ! '': $боевое_меню += "<<$меню_суперудар[6]>>
"
if $меню_суперудар[7] ! '': $боевое_меню += "<<$меню_суперудар[7]>>
"
if $меню_суперудар[8] ! '': $боевое_меню += "<<$меню_суперудар[8]>>
"

$боевое_меню += "
Back
"

gt 'боевой_интерфейс'

--- суперудары ---------------------------------


code:
# ход_противников
!CALCULATE THE ACTIONS QUEUE OF THE OPPONENTS
i = 0
:loop
if i < количество_врагов:
	i += 1
 	if враг[i] = 1:
  		gs '<<$интеллект[$враг[i]]>>'
	end
	jump 'loop'
end

gt 'конец_раунда'

--- ход_противников ---------------------------------


code:
import os

# folders currently supported by the engine, don't add more, it won't work this way
img_dir = ["girls/normal_scenes", "girls/sex_scenes", "girls/torture_scenes", "scene", "scene/service", "scene/gangbang"]

settings = {
	"rename_only": False
}

settings_file = open("settings.txt", "r")
for setting in settings_file:
	separator_index = setting.find('=')
	value = setting[separator_index+1:].strip()
	setting = setting[:separator_index].strip()

	settings[setting.lower()] = value.lower()

settings_file.close()

path = __file__[0:__file__.find(os.path.basename(__file__))]
game_path = path[:path.find("picture_modding")]
game_pic_path = game_path + "content/pic/"

pic_max = {}
pic_max_value = {}

# counting all the pictures.
for current_dir in img_dir:
	current_path = game_pic_path + current_dir

	for file in os.listdir(current_path):
		if file[-4:] == ".png" and "item" not in file:
			separator_index = file.rfind('_')
			if '0' <= file[separator_index + 1] <= '9':
				nr = int(file[separator_index+1:file.find(".png")])
				file = file[:separator_index]

				if nr == 1:
					pic_max_value[file] = 1

				elif pic_max_value[file] < nr:
					pic_max_value[file] = nr

			else:
				file = file[:-4]

			if file in pic_max:
				pic_max[file] += 1
			else:
				pic_max[file] = 1
				pic_max_value[file] = 1

bad_files = []

# checking indexing
for pic in pic_max:
	if pic_max[pic] != pic_max_value[pic]:
		bad_files.append(pic)

# attempting to fix indenting if there were any errors
if len(bad_files) > 0:
	ordered_files = {}
	for file in bad_files:
		ordered_files[file] = []
		for i in range(pic_max_value[file]+1):
			ordered_files[file].append(None)

	for current_dir in img_dir:
		current_path = game_pic_path + current_dir

		for file in os.listdir(current_path):
			if file[-4:] == ".png" and "item" not in file:
				separator_index = file.rfind('_')
				if '0' <= file[separator_index + 1] <= '9':
					nr = int(file[separator_index+1:file.find(".png")])
					file = file[:separator_index]
				else:
					nr = 1
					file = file[:-4]

				if file in bad_files:
					if ordered_files[file][0] == None:
						ordered_files[file][0] = current_path

					ordered_files[file][nr] = True

	for file in ordered_files:
		gap_index = None
		for i in range(2, len(ordered_files[file])-1):
			if ordered_files[file][i] is None:
				gap_index = i
				break

		for i in range(gap_index+1, len(ordered_files[file])):
			old_file = file + "_" + str(i)   + ".png"
			new_file = file + "_" + str(i-1) + ".png"

			os.rename(ordered_files[file][0] + '/' + old_file, ordered_files[file][0] + '/' + new_file)

# going through all new pictures, renaming and moving them
for current_dir in img_dir:
	current_path = path + "pic/" + current_dir
	relative_game_path = game_pic_path + current_dir

	for file in os.listdir(current_path):
		if file[-4:] == ".png":
			new_file = file[:-4]
			separator_index = new_file.rfind('(')
			if separator_index != -1:
				new_file = new_file[:separator_index].strip()

			separator_index = file.rfind('_')
			if '0' <= file[separator_index + 1] <= '9':
				new_file = new_file[:separator_index]

			if settings["rename_only"] == 'false':
				if new_file in pic_max:
					os.rename(current_path + '/' + file, relative_game_path + '/' + new_file + '_' + str(pic_max[new_file]+1) + ".png")
					pic_max[new_file] += 1

				else:
					os.rename(current_path + '/' + file, relative_game_path + '/' + new_file + ".png")
					pic_max[new_file] = 1

			else:
				if new_file in pic_max:
					os.rename(current_path + '/' + file, path + "renamed/" + current_dir + '/' + new_file + '_' + str(pic_max[new_file] + 1) + ".png")
					pic_max[new_file] += 1

				else:
					os.rename(current_path + '/' + file, path + "renamed/" + current_dir + '/' + new_file + ".png")
					pic_max[new_file] = 1

# doing one last check to make sure all multiple girl pics are named properly
for current_dir in img_dir:
	current_path = game_pic_path + current_dir

	for file in os.listdir(current_path):
		if file[-4:] == ".png" and "item" not in file:
			separator_index = file.rfind('_')
			if '~' in file:
				if '0' <= file[separator_index + 1] <= '9':
					multiple_girl_separator = file.find('~')
					fg = file[file.find("_")+1:multiple_girl_separator]
					sg = file[multiple_girl_separator+1:separator_index]
					if fg > sg and (("general" in fg and "general" in sg) or ("general" not in fg and "general" not in sg)):
						print(fg, sg)
						print(file + " --- Wrong girl order")

				else:
					multiple_girl_separator = file.find('~')
					fg = file[file.find("_")+1:multiple_girl_separator]
					sg = file[multiple_girl_separator+1:-4]
					if fg > sg and (("general" in fg and "general" in sg) or ("general" not in fg and "general" not in sg)):
						print(fg, sg)
						print(file + " --- Wrong girl order\n")


code:
Make sure the images are named properly: "*act*_*hair_color*_*hair_length*.png"
	-- numbering doesn't matter, just can let windows number them for you
	  	("*act*_*hair_color*_*hair_length*(*nr*).png")

Put the images you want to add into the folders above as if you were adding them to the game files yourself.

Run "add_pictures.py"
	-- Requires Python.

Done :D


seed_name: Isabella

seed_world_description: [Isabella]<br>- Not so very long ago we realized how huge the world is. When the ocean opened new rich land, everything changed. Power of the state is now measured by the force of his sailing fleet.

seed_family_description: [Isabella]<br>- I was born in the family of a simple fisherman, and since childhood I helped father to catch fish on the boat. I was always a tomboy. Then my parents died of smallpox, and I had to become a port whore.

seed_occupation_description: [Isabella]<br>- I certainly like to fuck, but I hate to earn money by this. I managed to get on a pirate ship, and a woman on a ship can get in trouble. But the pirates valued strength and savvy, and it does not matter who you are - black, crippled or woman.

fullimage: girls/full/isabela

seed_psy_basic: optimistic


code: start "" "game/engine/jack.exe" game/jack.qsp


code:
901_isabella.json is an improved Isabella who is mostly trained.  Copy this file into the game/json/slaves folder and replace.  This is considered a cheat provided by crushboss.

Jack_alternate_game_launch.bat is for those who have difficulty launching the game through the normal executable.
Copy this file into the Jack-o-nine-tails folder (the same folder containing Jack-o-nine-tails.exe) and double click on it to launch the game.


code:
<?xml version="1.0" encoding="utf-8"?>
<QGen-keywords>
  <Statements>
    <Keyword name="pl" desc="PL [выражение] / *PL [выражение] - вывод текста в дополнительное / основное окно описания, затем переход на новую строку"/>
    <Keyword name="clear" desc="CLEAR / *CLEAR - очистка дополнительного / основного окна описания"/>
    <Keyword name="clr" desc="CLR / *CLR - очистка дополнительного / основного окна описания"/>
    <Keyword name="p" desc="P [выражение] / *P [выражение] - вывод текста в дополнительное / основное окно описания"/>
    <Keyword name="nl" desc="NL [выражение] / *NL [выражение] - переход на новую строку, затем вывод текста в дополнительное / основное окно описания"/>
    <Keyword name="msg" desc="MSG [выражение] - вывод сообщения в информационном окне"/>
    <Keyword name="wait" desc="WAIT [#выражение] - остановка выполнения программы на заданное количество миллисекунд"/>
    <Keyword name="act" desc="ACT [$название],[$путь к изображению]:[оператор] & [оператор] & ... - добавление действия"/>
    <Keyword name="delact" desc="DELACT [$название] / DEL ACT [$название] - удаление действия"/>
    <Keyword name="cla" desc="CLA - очистка списка действий"/>
    <Keyword name="cmdclear" desc="CMDCLEAR - очистка строки ввода"/>
    <Keyword name="cmdclr" desc="CMDCLEAR - очистка строки ввода"/>
    <Keyword name="cls" desc="CLS - очищает экран, оставляя только список предметов"/>
    <Keyword name="menu" desc="MENU [$выражение] - показ меню с заданным названием"/>
    <Keyword name="settimer" desc="SETTIMER [#выражение] - задает интервал таймера для локации-счетчика"/>
    <Keyword name="dynamic" desc="DYNAMIC [$строка кода],[параметр 1],[параметр 2], ... - динамическое выполнение кода"/>
    <Keyword name="set" desc="SET [название переменной]=[выражение] - установка значения переменной"/>
    <Keyword name="let" desc="LET [название переменной]=[выражение] - установка значения переменной"/>
    <Keyword name="killvar" desc="KILLVAR [$название],[#индекс] - удаление всех переменных / указанной переменной"/>
    <Keyword name="copyarr" desc="COPYARR [$массив-приемник],[$массив-источник] - копирование содержимого массива в другой массив"/>
    <Keyword name="addobj" desc="ADDOBJ [$название],[$путь к изображению],[#позиция] / ADD OBJ [$название],[$путь к изображению],[#позиция] - добавление предмета"/>
    <Keyword name="delobj" desc="DELOBJ [$название] / DEL OBJ [$название] - удаление предмета"/>
    <Keyword name="killobj" desc="KILLOBJ [#позиция] - удаление всех предметов / предмета в заданной позиции"/>
    <Keyword name="unselect" desc="UNSELECT - отмена выбора предмета"/>
    <Keyword name="unsel" desc="UNSEL - отмена выбора предмета"/>
    <Keyword name="killall" desc="KILLALL - удаление всех переменных и предметов"/>
    <Keyword name="opengame" desc="OPENGAME [$выражение] - загрузка состояния игры"/>
    <Keyword name="openqst" desc="OPENQST [$выражение] - открытие и запуск файла игры"/>
    <Keyword name="addqst" desc="ADDQST [$выражение] - добавление локаций из указанного файла"/>
    <Keyword name="killqst" desc="KILLQST - удаление всех добавленных через ADDQST локаций"/>
    <Keyword name="savegame" desc="SAVEGAME [$выражение] - сохранение состояния игры"/>
    <Keyword name="refint" desc="REFINT - обновление интерфейса"/>
    <Keyword name="showacts" desc="SHOWACTS [#выражение] - показ / скрытие списка действий"/>
    <Keyword name="showinput" desc="SHOWINPUT [#выражение] - показ / скрытие строки ввода"/>
    <Keyword name="showobjs" desc="SHOWOBJS [#выражение] - показ / скрытие списка предметов"/>
    <Keyword name="showstat" desc="SHOWSTAT [#выражение] - показ / скрытие дополнительного окна описания"/>
    <Keyword name="if" desc="IF [#выражение]:[оператор1] & [оператор2] & ... ELSE [оператор3] & [оператор4] & ... - условие"/>
    <Keyword name="else" desc="IF [#выражение]:[оператор1] & [оператор2] & ... ELSE [оператор3] & [оператор4] & ... - условие"/>
    <Keyword name="elseif" desc="ELSEIF [#выражение]:[оператор1] & [оператор2] & ... - альтернативное условие"/>
    <Keyword name="exit" desc="EXIT - завершение выполнения текущего кода"/>
    <Keyword name="end" desc="END - завершение многострочной формы IF / ACT"/>
    <Keyword name="jump" desc="JUMP [$выражение] - переход на указанную метку"/>
    <Keyword name="gosub" desc="GOSUB [$выражение],[параметр 1],[параметр 2], ... - обработка указанной локации"/>
    <Keyword name="gs" desc="GS [$выражение],[параметр 1],[параметр 2], ... - обработка указанной локации"/>
    <Keyword name="goto" desc="GOTO [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию"/>
    <Keyword name="gt" desc="GT [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию"/>
    <Keyword name="xgoto" desc="XGOTO [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию без очистки основного окна описания"/>
    <Keyword name="xgt" desc="XGT [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию без очистки основного окна описания"/>
    <Keyword name="play" desc="PLAY [$путь к звуковому файлу],[#громкость] - воспроизведение звукового файла с заданной громкостью"/>
    <Keyword name="close" desc="CLOSE [$путь к звуковому файлу] / CLOSE ALL - остановка проигрывания звукового файла / всех звуковых файлов"/>
    <Keyword name="view" desc="VIEW [$путь к графическому файлу] - просмотр изображения"/>
  </Statements>
  <Expressions>
    <Keyword name="and" desc="[#выражение 1] AND [#выражение 2] - логическое "и=""/>
    <Keyword name="or" desc="[#выражение 1] OR [#выражение 2] - логическое "или""/>
    <Keyword name="obj" desc="OBJ [$предмет] - проверка наличия предмета в рюкзаке"/>
    <Keyword name="loc" desc="LOC [$локация] - проверка существования локации"/>
    <Keyword name="no" desc="NO [#выражение] - отрицание"/>
    <Keyword name="mod" desc="[#выражение 1] MOD [#выражение 2] - вычисление остатка от деления"/>
    <Keyword name="desc" desc="DESC([$выражение]) - возвращает текст базового описания локации"/>
    <Keyword name="$desc" desc="$DESC([$выражение]) - возвращает текст базового описания локации"/>
    <Keyword name="iif" desc="IIF([#выражение],[выражение_да],[выражение_нет]) - возвращает одно из выражений по условию"/>
    <Keyword name="$iif" desc="$IIF([#выражение],[выражение_да],[выражение_нет]) - возвращает одно из выражений по условию"/>
    <Keyword name="input" desc="INPUT([выражение]) - показывает окно ввода текста и возвращает введенное значение"/>
    <Keyword name="$input" desc="$INPUT([выражение]) - показывает окно ввода текста и возвращает введенное значение"/>
    <Keyword name="isplay" desc="ISPLAY([$выражение]) - проверяет, проигрывается ли в текущий момент указанный файл"/>
    <Keyword name="max" desc="MAX([выражение 1],[выражение 2], ...) - возвращает максимальное из значений аргументов"/>
    <Keyword name="$max" desc="$MAX([выражение 1],[выражение 2], ...) - возвращает максимальное из значений аргументов"/>
    <Keyword name="min" desc="MIN([выражение 1],[выражение 2], ...) - возвращает минимальное из значений аргументов"/>
    <Keyword name="$min" desc="$MIN([выражение 1],[выражение 2], ...) - возвращает минимальное из значений аргументов"/>
    <Keyword name="rand" desc="RAND([#выражение 1],[#выражение 2]) - возвращает случайное число между заданными"/>
    <Keyword name="rgb" desc="RGB([#красный],[#зеленый],[#синий]) - возвращает код цвета на основе 3-х составляющих"/>
    <Keyword name="getobj" desc="GETOBJ([#позиция]) - возвращает название предмета, расположенного в заданной позиции"/>
    <Keyword name="$getobj" desc="$GETOBJ([#позиция]) - возвращает название предмета, расположенного в заданной позиции"/>
    <Keyword name="dyneval" desc="DYNEVAL([$выражение],[параметр 1],[параметр 2], ...) - возвращает значение динамически вычисленного выражения"/>
    <Keyword name="$dyneval" desc="$DYNEVAL([$выражение],[параметр 1],[параметр 2], ...) - возвращает значение динамически вычисленного выражения"/>
    <Keyword name="func" desc="FUNC([$выражение],[параметр 1],[параметр 2], ...) - обработка указанной локации как функции"/>
    <Keyword name="$func" desc="$FUNC([$выражение],[параметр 1],[параметр 2], ...) - обработка указанной локации как функции"/>
    <Keyword name="arrsize" desc="ARRSIZE([$выражение]) - возвращает число элементов в указанном массиве"/>
    <Keyword name="arrpos" desc="ARRPOS([#начальный индекс],[$имя массива],[значение]) - поиск в массиве элемента с заданным значением"/>
    <Keyword name="instr" desc="INSTR([#начальная позиция],[$текст],[$искомый текст]) - поиск вхождения текста"/>
    <Keyword name="isnum" desc="ISNUM([$выражение]) - проверяет, является ли указанная строка числом"/>
    <Keyword name="trim" desc="TRIM([$выражение]) - удаляет из текста прилегающие пробелы и символы табуляции"/>
    <Keyword name="$trim" desc="$TRIM([$выражение]) - удаляет из текста прилегающие пробелы и символы табуляции"/>
    <Keyword name="ucase" desc="UCASE([$выражение]) - преобразует маленькие буквы текста в большие"/>
    <Keyword name="$ucase" desc="$UCASE([$выражение]) - преобразует маленькие буквы текста в большие"/>
    <Keyword name="lcase" desc="LCASE([$выражение]) - преобразует большие буквы текста в маленькие"/>
    <Keyword name="$lcase" desc="$LCASE([$выражение]) - преобразует большие буквы текста в маленькие"/>
    <Keyword name="len" desc="LEN([$выражение]) - возвращает длину указанной строки"/>
    <Keyword name="mid" desc="MID([$текст],[#начало],[#длина]) - вырезает из текста строку указанной длины начиная с заданной позиции"/>
    <Keyword name="$mid" desc="$MID([$текст],[#начало],[#длина]) - вырезает из текста строку указанной длины начиная с заданной позиции"/>
    <Keyword name="replace" desc="REPLACE([$текст],[$искомый текст],[$текст для замены]) - заменяет в тексте заданную строку"/>
    <Keyword name="$replace" desc="$REPLACE([$текст],[$искомый текст],[$текст для замены]) - заменяет в тексте заданную строку"/>
    <Keyword name="str" desc="STR([#выражение]) - переводит число в строку"/>
    <Keyword name="$str" desc="$STR([#выражение]) - переводит число в строку"/>
    <Keyword name="val" desc="VAL([$выражение]) - переводит строку в число"/>
    <Keyword name="arrcomp" desc="ARRCOMP([#начальный индекс],[$имя массива],[$шаблон]) - поиск в массиве элемента, соответствующего регулярному выражению"/>
    <Keyword name="strcomp" desc="STRCOMP([$выражение],[$шаблон]) - проверяет заданный текст на соответствие регулярному выражению"/>
    <Keyword name="strfind" desc="STRFIND([$выражение],[$шаблон],[#номер]) - возвращает подстроку, соответствующую группе с номером [#номер] регулярного выражения"/>
    <Keyword name="$strfind" desc="$STRFIND([$выражение],[$шаблон],[#номер]) - возвращает подстроку, соответствующую группе с номером [#номер] регулярного выражения"/>
    <Keyword name="strpos" desc="STRPOS([$выражение],[$шаблон],[#номер]) - возвращает позицию подстроки, соответствующей группе с номером [#номер] регулярного выражения"/>
    <Keyword name="countobj" desc="COUNTOBJ - возвращает текущее число предметов"/>
    <Keyword name="msecscount" desc="MSECSCOUNT - возвращает количество миллисекунд, прошедших с момента начала игры"/>
    <Keyword name="rnd" desc="RND - возвращает случайное значение от 1 до 1000"/>
    <Keyword name="curloc" desc="CURLOC - возвращает название текущей локации"/>
    <Keyword name="$curloc" desc="$CURLOC - возвращает название текущей локации"/>
    <Keyword name="qspver" desc="QSPVER - возвращает версию интерпретатора"/>
    <Keyword name="$qspver" desc="$QSPVER - возвращает версию интерпретатора"/>
    <Keyword name="selobj" desc="SELOBJ - возвращает название выделенного предмета"/>
    <Keyword name="$selobj" desc="$SELOBJ - возвращает название выделенного предмета"/>
    <Keyword name="selact" desc="SELACT - возвращает название выделенного действия"/>
    <Keyword name="$selact" desc="$SELACT - возвращает название выделенного действия"/>
    <Keyword name="curacts" desc="CURACTS - возвращает в виде кода все текущие действия"/>
    <Keyword name="$curacts" desc="$CURACTS - возвращает в виде кода все текущие действия"/>
    <Keyword name="user_text" desc="USER_TEXT - возвращает текст в строке ввода"/>
    <Keyword name="$user_text" desc="$USER_TEXT - возвращает текст в строке ввода"/>
    <Keyword name="usrtxt" desc="USRTXT - возвращает текст в строке ввода"/>
    <Keyword name="$usrtxt" desc="$USRTXT - возвращает текст в строке ввода"/>
    <Keyword name="maintxt" desc="MAINTXT - возвращает текст в основном окне описания"/>
    <Keyword name="$maintxt" desc="$MAINTXT - возвращает текст в основном окне описания"/>
    <Keyword name="stattxt" desc="STATTXT - возвращает текст в дополнительном окне описания"/>
    <Keyword name="$stattxt" desc="$STATTXT - возвращает текст в дополнительном окне описания"/>
  </Expressions>
  <Variables>
    <Keyword name="args" desc="ARGS - массив с параметрами процедуры / функции"/>
    <Keyword name="$args" desc="$ARGS - массив с параметрами процедуры / функции"/>
    <Keyword name="result" desc="RESULT - переменная содержит результат, возвращаемый текущей функцией"/>
    <Keyword name="$result" desc="$RESULT - переменная содержит результат, возвращаемый текущей функцией"/>
    <Keyword name="disablescroll" desc="DISABLESCROLL - если переменная не равна 0, то запрещает автопрокрутку текста при выводе"/>
    <Keyword name="disablesubex" desc="DISABLESUBEX - если переменная не равна 0, то запрещает использование "подвыражений" в тексте"/>
    <Keyword name="nosave" desc="NOSAVE - если переменная не равна 0, то сохранение состояния игры пользователем невозможно"/>
    <Keyword name="debug" desc="DEBUG - если переменная не равна 0, то отключается проверка идентификатора игры при загрузке состояния"/>
    <Keyword name="$counter" desc="$COUNTER - переменная содержит название локации-счётчика"/>
    <Keyword name="$ongload" desc="$ONGLOAD - переменная содержит название локации-обработчика загрузки состояния"/>
    <Keyword name="$ongsave" desc="$ONGSAVE - переменная содержит название локации-обработчика сохранения состояния"/>
    <Keyword name="$onnewloc" desc="$ONNEWLOC - переменная содержит название локации-обработчика перехода на новую локацию"/>
    <Keyword name="$onactsel" desc="$ONACTSEL - переменная содержит название локации-обработчика выбора действия"/>
    <Keyword name="$onobjsel" desc="$ONOBJSEL - переменная содержит название локации-обработчика выбора предмета"/>
    <Keyword name="$onobjadd" desc="$ONOBJADD - переменная содержит название локации-обработчика добавления предмета"/>
    <Keyword name="$onobjdel" desc="$ONOBJDEL - переменная содержит название локации-обработчика удаления предмета"/>
    <Keyword name="$usercom" desc="$USERCOM - переменная содержит название локации-обработчика строки ввода"/>
    <Keyword name="usehtml" desc="USEHTML - если переменная не равна 0, то включает возможность использования HTML"/>
    <Keyword name="bcolor" desc="BCOLOR - переменная содержит цвет фона"/>
    <Keyword name="fcolor" desc="FCOLOR - переменная содержит основной цвет шрифта"/>
    <Keyword name="lcolor" desc="LCOLOR - переменная содержит основной цвет ссылок"/>
    <Keyword name="fsize" desc="FSIZE - переменная содержит основной размер шрифта"/>
    <Keyword name="$fname" desc="$FNAME - переменная содержит название основного шрифта"/>
    <Keyword name="$backimage" desc="$BACKIMAGE - переменная содержит путь к фоновому изображению"/>
  </Variables>
</QGen-keywords>


code:
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain

repo_name: Angedore/rjw

path: .gitattributes


code:
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb

path: .gitignore


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<JobDef>
		<defName>WhoreIsServingVisitors</defName>
		<driverClass>rjwwhoring.JobDriver_WhoreIsServingVisitors</driverClass>
		<reportString>serving visitors</reportString>
		<casualInterruptible>false</casualInterruptible>
	</JobDef>

	<JobDef>
		<defName>WhoreInvitingVisitors</defName>
		<driverClass>rjwwhoring.JobDriver_WhoreInvitingVisitors</driverClass>
		<reportString>attempting hookup</reportString>
		<casualInterruptible>false</casualInterruptible>
	</JobDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>

	<RecordDef>
		<defName>CountOfWhore</defName>
		times whored
		<description>The number of times I whored myself.</description>
		<type>Int</type>
	</RecordDef>

	<RecordDef>
		<defName>EarnedMoneyByWhore</defName>
		silvers earned as a whore
		<description>The amount of silvers I have earned as a whore.</description>
		<type>Int</type>
	</RecordDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>

	<RoomRoleDef>
		<defName>Brothel</defName>
		brothel
		<workerClass>rjwwhoring.RoomRoleWorker_Brothel</workerClass>
		<relatedStats>

Beauty

Cleanliness

Wealth

Space

Impressiveness

		</relatedStats>
	</RoomRoleDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<ThinkTreeDef>
		<defName>PrisonerWhoreSexualEmergencyTree</defName>
		<insertTag>Humanlike_PostDuty</insertTag>
		<insertPriority>100</insertPriority>
		<thinkRoot Class="ThinkNode_Priority">
			<subNodes>

					<subNodes>

							<subNodes>

							</subNodes>

					</subNodes>

			</subNodes>
		</thinkRoot>
	</ThinkTreeDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>

	<ThinkTreeDef>
		<defName>WhoreSexualEmergencyTree</defName>
		<insertTag>Humanlike_PreMain</insertTag>
		<insertPriority>15</insertPriority>
		<thinkRoot Class="ThinkNode_Priority">
			<subNodes>

					<subNodes>

							<subNodes>

							</subNodes>

					</subNodes>

			</subNodes>
		</thinkRoot>
	</ThinkTreeDef>

	<ThinkTreeDef>
		<defName>WhoreJobTree</defName>
		<insertTag>Humanlike_PostMain</insertTag>
		<insertPriority>15</insertPriority>
		<thinkRoot Class="ThinkNode_Priority">
			<subNodes>

					<subNodes>

							<subNodes>

							</subNodes>

					</subNodes>

			</subNodes>
		</thinkRoot>
	</ThinkTreeDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<rjwwhoring.ThoughtDef_Whore>
		<defName>Whorish_Thoughts</defName>
		<thoughtClass>rjwwhoring.ThoughtWorker_Whore</thoughtClass>
		<durationDays>2.0</durationDays>
		<stackLimit>10</stackLimit>
		<stackedEffectMultiplier>0.4</stackedEffectMultiplier>

		<stageCounts>

30

50

		</stageCounts>
		<storyOffset>30</storyOffset>
		<stages>

				Resentful whore
				<description>We just need money! I'm not a ...</description>
				<baseMoodEffect>-5</baseMoodEffect>

				Whore
				<description>Well, at least it pays well...</description>
				<baseMoodEffect>-1</baseMoodEffect>

				WHORE
				<description>This job isn't so bad afterall!</description>
				<baseMoodEffect>2</baseMoodEffect>

		</stages>
	</rjwwhoring.ThoughtDef_Whore>

	<rjwwhoring.ThoughtDef_Whore>
		<defName>Whorish_Thoughts_Captive</defName>
		<thoughtClass>rjwwhoring.ThoughtWorker_Whore</thoughtClass>
		<durationDays>4.0</durationDays>
		<stackLimit>10</stackLimit>
		<stackedEffectMultiplier>0.4</stackedEffectMultiplier>

		<stageCounts>

30

40

80

		</stageCounts>
		<storyOffset>10</storyOffset>

		<stages>

				Forced whore
				<description>They forced me to serve as a sex toy!</description>
				<baseMoodEffect>-20</baseMoodEffect>

				Unwilling whore
				<description>I'm not just a rental ride!</description>
				<baseMoodEffect>-10</baseMoodEffect>

				Accustomed whore
				<description>Just no beatings, please.</description>
				<baseMoodEffect>-1</baseMoodEffect>

				Complete whore
				<description>I could get more clients if not these restraints!</description>
				<baseMoodEffect>2</baseMoodEffect>

		</stages>
	</rjwwhoring.ThoughtDef_Whore>

	<ThoughtDef>
		<defName>RJWFailedSolicitation</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>0.4</durationDays>
		<stackLimit>100</stackLimit>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
		<stages>

				tried to solicit me
				<baseOpinionOffset>-1</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>RJWTurnedDownWhore</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>0.2</durationDays>
		<stackLimit>1</stackLimit>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
		<stages>

				bothered me
				<baseOpinionOffset>-1</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>SleptInBrothel</defName>
		<durationDays>1</durationDays>
		<stackedEffectMultiplier>1</stackedEffectMultiplier>
		<stackLimit>1</stackLimit>
		<stages>

				slept in brothel
				<description>Eww, the sheets were all sticky.</description>
				<baseMoodEffect>-10</baseMoodEffect>

				slept in brothel!
				<description>I just love this place, the smell, the sounds...</description>
				<baseMoodEffect>2</baseMoodEffect>

		</stages>
	</ThoughtDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<TipSetDef>
		<defName>RjwWhoringTips</defName>
		<tips>

Whoring price is visible in the "show sexuality" menu on the bio tab (the icon looks like a heart).

Condoms can be automatically used if placed in a stockpile next to a bed - it might be a good idea to have some around if you intend on whoring your colonists out.

		</tips>
	</TipSetDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>

	<rjwwhoring.StringListDef>
		<defName>WhoreBackstories</defName>
		<strings>

Sex slave

Courtesean

Housemate

Model

idol

Nymph

Pleasure

Courtesan

Dancer

Holo-star

Prostitute

Breeder

		</strings>
	</rjwwhoring.StringListDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<MainButtonDef>
		<defName>RJW_Brothel</defName>
		<label>Brothel</label>
		<description>List whores in the area.</description>
		<tabWindowClass>rjwwhoring.MainTab.MainTabWindow_Brothel</tabWindowClass>
		<order>53</order>
		<minimized>True</minimized>
		<iconPath>UI/Commands/Service_off</iconPath>
	</MainButtonDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>
	<PawnColumnDef>
		<defName>RJW_IsWhore</defName>
		<headerTip>Whores</headerTip>
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_IsWhore</workerClass>
		<sortable>true</sortable>
		<width>80</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_IsPrisoner</defName>
		<headerTip>Prisoners</headerTip>
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_IsPrisoner</workerClass>
		<sortable>true</sortable>
		<width>80</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_IsSlave</defName>
		<headerTip>Slaves</headerTip>
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_IsSlave</workerClass>
		<sortable>true</sortable>
		<width>80</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_WhoreExperience</defName>
		<headerTip>Whoring experience</headerTip>
		Experience
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_WhoreExperience</workerClass>
		<width>100</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_PriceRangeOfWhore</defName>
		<headerTip>Price range for whore</headerTip>
		Price
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_PriceRangeOfWhore</workerClass>
		<width>100</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_EarnedMoneyByWhore</defName>
		<headerTip>Money earned(total)</headerTip>
		Earned
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_EarnedMoneyByWhore</workerClass>
		<width>100</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_CountOfWhore</defName>
		<headerTip>Clients served</headerTip>
		Clients
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_CountOfWhore</workerClass>
		<width>100</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_AverageMoneyByWhore</defName>
		<headerTip>Money earned(average)</headerTip>
		Average
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_AverageMoneyByWhore</workerClass>
		<width>100</width>
	</PawnColumnDef>
	<PawnColumnDef>
		<defName>RJW_WhoreMood</defName>
		<headerTip>Mood of pawn</headerTip>
		Mood
		<workerClass>rjwwhoring.MainTab.PawnColumnWorker_Mood</workerClass>
		<width>100</width>
	</PawnColumnDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>

	<PawnTableDef>
		<defName>RJW_Brothel</defName>
		<workerClass>rjwwhoring.MainTab.PawnTable_Whores</workerClass>
		<columns>

Label

GapTiny

RJW_Gender

GapTiny

LifeStage

GapTiny

RJW_IsWhore

RJW_IsPrisoner

RJW_IsSlave

RJW_WhoreMood

GapTiny

RJW_CountOfWhore

RJW_WhoreExperience

RJW_EarnedMoneyByWhore

RJW_AverageMoneyByWhore

GapTiny

RJW_PriceRangeOfWhore

RemainingSpace

		</columns>
		<modExtensions>

				Brothel

		</modExtensions>
	</PawnTableDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
	<whoringtab_enabled>Enable whoring tab</whoringtab_enabled>
	<whoringtab_enabled_desc>Shows/hide whoring tab</whoringtab_enabled_desc>
	<show_whore_price_factor_on_bed>Show whore price factor on beds</show_whore_price_factor_on_bed>
	<show_whore_price_factor_on_bed_desc>Show whore price factor as a label on beds that are enabled for whoring.</show_whore_price_factor_on_bed_desc>
	<show_whore_widgets_on_bed>Show bed widgets</show_whore_widgets_on_bed>
	<show_whore_widgets_on_bed_desc>Show bed widgets to mark beds for public/private for whoring.</show_whore_widgets_on_bed_desc>

	<MoneyPrinting>Money Printing</MoneyPrinting>
	<MoneyPrinting_desc>Clients will spawn silver instead of using their own/caravan</MoneyPrinting_desc>
	<ClientAlwaysAccept>Client RNG disable</ClientAlwaysAccept>
	<ClientAlwaysAccept_desc>Instead of doing rng roll, Clients always accept solicitation.</ClientAlwaysAccept_desc>

	<DebugWhoring>Debug log whoring info</DebugWhoring>
	<DebugWhoring_desc>Enables some very spamming debug logs to help find bugs in Whoring solicitation operations.</DebugWhoring_desc>

	<!--Whore Activities-->
	<RJW_VisitorAcceptWhore>{0} accepted the deal {1} offered.</RJW_VisitorAcceptWhore>
	<RJW_VisitorSolicitWhore>{0} wants to be serviced by {1}.</RJW_VisitorSolicitWhore>
	<RJW_VisitorRejectWhore>{0} rejected the deal {1} offered.</RJW_VisitorRejectWhore>
	<RJW_VisitorSickWhore>{0} rejected the offer because {1} does not look healthy</RJW_VisitorSickWhore>

	<!--Whore designators-->
	<ForService>Assign to whorin'</ForService> <!-- This field is not visible -->
	<ForServiceDesc><![CDATA[Mark for whoring
- Will try to hook up with visitors.
- Entertains other colonists if not busy.
- Tries to refrain from masturbation while on the job, may cause frustration.
]]></ForServiceDesc>
	<ForServiceRefuseDesc>Won't agree to be a whore</ForServiceRefuseDesc>

	<!--Bed designators-->
	<CommandBedSetAsWhoreBedLabel>Allow everyone to whore</CommandBedSetAsWhoreBedLabel>
	<CommandBedSetAsWhoreBedDesc>Allow all whores to use this bed to entertain customers.</CommandBedSetAsWhoreBedDesc>
	<CommandBedAllowWhoringLabel>Allow owner to whore</CommandBedAllowWhoringLabel>
	<CommandBedAllowWhoringDesc>Whether owner(s) are allowed to use this bed for whoring.</CommandBedAllowWhoringDesc>
	<WhorePriceCalcDesc>Whoring price factor (based on comfort, room impressiveness and number of beds in room: {0}</WhorePriceCalcDesc>

	<WhorePrice>Whoring price range: </WhorePrice>
	<BrothelTabIsPrisoner>Prisoner</BrothelTabIsPrisoner>
	<BrothelTabIsSlave>Slave</BrothelTabIsSlave>
</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<Patch>
  <Operation Class="PatchOperationFindMod">
    <mods>

[NL] Facial Animation - WIP

    </mods>
    <match Class="PatchOperationSequence">
      <success>Always</success>
      <operations>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/targetJobs</xpath>
          <success>Always</success>
          <value>

WhoreIsServingVisitors

          </value>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="StandAndBeSociallyActive"]/targetJobs</xpath>
          <success>Always</success>
          <value>

WhoreInvitingVisitors

          </value>

      </operations>
    </match>
  </Operation>
</Patch>


code:
using System;
using Verse;
using System.Linq;
using RimWorld;

namespace rjwwhoring
{
	public class BedData : IExposable
	{
		public Building_Bed bed = null;
		public bool allowedForWhoringOwner = true;
		public bool allowedForWhoringAll = false;
		public int reservedUntilGameTick = 0;
		public int reservedForPawnID = 0;

		public int lastScoreUpdateTick = -70; // GenTicks.TicksGame
		public float bedScore = -1f;
		public int scoreUpdateTickDelay = 60;

		public float roomScore = -1f;

		public BedData() { }
		public BedData(Building_Bed bed)
		{
			this.bed = bed;
		}

		public void ExposeData()
		{
			Scribe_References.Look(ref bed, "Bed");
			Scribe_Values.Look(ref allowedForWhoringOwner, "allowedForWhoringOwner", true, true);
			Scribe_Values.Look(ref allowedForWhoringAll, "allowedForWhoringAll", false, true);
			Scribe_Values.Look(ref reservedUntilGameTick, "lastUsed", 0, true);
			Scribe_Values.Look(ref reservedForPawnID, "lastUsedBy", 0, true);
		}

		public bool IsValid { get { return bed != null; } }
	}
}


code:
using System.Collections.Generic;
using Verse;
using RimWorld;
using RimWorld.Planet;

namespace rjwwhoring
{
	/// <summary>
	/// Rimworld object for storing the world/save info
	/// </summary>
	public class DataStore : WorldComponent
	{
		public Dictionary<int, BedData> bedData = new Dictionary<int, BedData>();

		public DataStore(World world) : base(world)
		{
		}

		public override void ExposeData()
		{
			if (Scribe.mode == LoadSaveMode.Saving)
			{
				bedData.RemoveAll(item => item.Value == null || !item.Value.IsValid);
			}

			base.ExposeData();
			Scribe_Collections.Look(ref bedData, "BedData", LookMode.Value, LookMode.Deep);
			if (Scribe.mode == LoadSaveMode.LoadingVars)
			{
				if (bedData == null) bedData = new Dictionary<int, BedData>();
			}
		}

		public BedData GetBedData(Building_Bed bed)
		{
			BedData res;
			var filled = bedData.TryGetValue(bed.thingIDNumber, out res);
			if ((res == null) || (!res.IsValid))
			{
				if (filled)
				{
					bedData.Remove(bed.thingIDNumber);
				}
				res = new BedData(bed);
				bedData.Add(bed.thingIDNumber, res);
			}
			return res;
		}
	}
}


code:
using System.Collections.Generic;
using Verse;

namespace rjwwhoring
{
	/// <summary>
	/// Whore backstories from xml GET!
	/// Just a simplest form of passing data from xml to the code
	/// </summary>
	public class StringListDef : Def
	{
		public List<string> strings = new List<string>();
	}
}


code:
using RimWorld;
using Verse;

namespace rjwwhoring
{
	[DefOf]
	public static class RecordDefOf
	{
		public static RecordDef EarnedMoneyByWhore;
		public static RecordDef CountOfWhore;
	}
}


code:
using RimWorld;
using Verse;

namespace rjwwhoring
{
    [DefOf]
    public static class ThoughtDefOf
    {
        public static ThoughtDef_Whore Whorish_Thoughts;

        public static ThoughtDef_Whore Whorish_Thoughts_Captive;

        public static ThoughtDef SleptInBrothel;

        public static ThoughtDef RJWFailedSolicitation;

        public static ThoughtDef RJWTurnedDownWhore;
    }
}


code:
using System.Collections.Generic;
using RimWorld;
using rjw;
using Verse;
using Verse.AI;

namespace rjwwhoring
{
	public class JobDriver_WhoreInvitingVisitors : JobDriver
	{
		// List of jobs that can be interrupted by whores.
		public static readonly List<JobDef> allowedJobs = new List<JobDef> { null, JobDefOf.Wait_Wander, JobDefOf.GotoWander, JobDefOf.Clean, JobDefOf.ClearSnow,
			JobDefOf.CutPlant, JobDefOf.HaulToCell, JobDefOf.Deconstruct, JobDefOf.Harvest, JobDefOf.LayDown, JobDefOf.Research, JobDefOf.SmoothFloor, JobDefOf.SmoothWall,
			JobDefOf.SocialRelax, JobDefOf.StandAndBeSociallyActive, JobDefOf.RemoveApparel, JobDefOf.Strip, JobDefOf.Tame, JobDefOf.Wait, JobDefOf.Wear, JobDefOf.FixBrokenDownBuilding,
			JobDefOf.FillFermentingBarrel, JobDefOf.DoBill, JobDefOf.Sow, JobDefOf.Shear, JobDefOf.BuildRoof, JobDefOf.DeliverFood,	JobDefOf.HaulToContainer, JobDefOf.Hunt, JobDefOf.Mine,
			JobDefOf.OperateDeepDrill, JobDefOf.OperateScanner, JobDefOf.RearmTurret, JobDefOf.Refuel, JobDefOf.RefuelAtomic, JobDefOf.RemoveFloor, JobDefOf.RemoveRoof, JobDefOf.Repair,
			JobDefOf.TakeBeerOutOfFermentingBarrel, JobDefOf.Train, JobDefOf.Uninstall, xxx.Masturbate};

		public bool successfulPass = true;

		private Pawn Whore => GetActor();
		private Pawn TargetPawn => TargetThingA as Pawn;
		private Building_Bed TargetBed => TargetThingB as Building_Bed;

		private readonly TargetIndex TargetPawnIndex = TargetIndex.A;
		private readonly TargetIndex TargetBedIndex = TargetIndex.B;

		private bool DoesTargetPawnAcceptAdvance()
		{
			if (WhoringBase.DebugWhoring) ModLog.Message($"JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() - {xxx.get_pawnname(TargetPawn)}");
			//if (RJWSettings.WildMode) return true;

			if (PawnUtility.EnemiesAreNearby(TargetPawn))
			{
				if (WhoringBase.DebugWhoring) ModLog.Message($" fail - enemy near");
				return false;
			}
			if (!allowedJobs.Contains(TargetPawn.jobs.curJob.def))
			{
				if (WhoringBase.DebugWhoring) ModLog.Message($" fail - not allowed job");
				return false;
			}

			if (WhoringBase.DebugWhoring)
			{
				ModLog.Message("Will try hookup " + WhoringHelper.WillPawnTryHookup(TargetPawn));
				ModLog.Message("Is whore appealing  " + WhoringHelper.IsHookupAppealing(TargetPawn, Whore));
				ModLog.Message("Can afford whore " + WhoringHelper.CanAfford(TargetPawn, Whore));
				ModLog.Message("Need sex " + (xxx.need_some_sex(TargetPawn) >= 1));
			}
			if (WhoringHelper.WillPawnTryHookup(TargetPawn) && WhoringHelper.IsHookupAppealing(TargetPawn, Whore) && WhoringHelper.CanAfford(TargetPawn, Whore) && xxx.need_some_sex(TargetPawn) >= 1f)
			{
				if (!Whore.IsPrisoner)
					Whore.skills.Learn(SkillDefOf.Social, 1.2f);
				return true;
			}
			return false;
		}

		public override bool TryMakePreToilReservations(bool errorOnFailed) => true;

		protected override IEnumerable<Toil> MakeNewToils()
		{
			this.FailOnDespawnedOrNull(TargetPawnIndex);
			this.FailOnDespawnedNullOrForbidden(TargetBedIndex);
			this.FailOn(() => Whore is null || !WhoreBed_Utility.CanUseForWhoring(Whore, TargetBed));//|| !Whore.CanReserve(TargetPawn)
			this.FailOn(() => pawn.Drafted);

			if (!Whore.IsPrisoner)
			{
				yield return Toils_Goto.GotoThing(TargetPawnIndex, PathEndMode.Touch);

				Toil TryItOn = new Toil();
				TryItOn.AddFailCondition(() => !xxx.IsTargetPawnOkay(TargetPawn));
				TryItOn.defaultCompleteMode = ToilCompleteMode.Delay;
				TryItOn.initAction = delegate
				{
					//ModLog.Message("JobDriver_InvitingVisitors::MakeNewToils - TryItOn - initAction is called");
					Whore.jobs.curDriver.ticksLeftThisToil = 50;
					FleckMaker.ThrowMetaIcon(Whore.Position, Whore.Map, FleckDefOf.Heart);
				};
				yield return TryItOn;
			}

			Toil AwaitResponse = new Toil();
			AwaitResponse.defaultCompleteMode = ToilCompleteMode.Delay;
			AwaitResponse.defaultDuration = 10;
			AwaitResponse.initAction = delegate
			{
				List<RulePackDef> extraSentencePacks = new List<RulePackDef>();
				successfulPass = DoesTargetPawnAcceptAdvance();
				//ModLog.Message("JobDriver_InvitingVisitors::MakeNewToils - AwaitResponse - initAction is called");
				if (successfulPass)
				{
					FleckMaker.ThrowMetaIcon(TargetPawn.Position, TargetPawn.Map, FleckDefOf.Heart);
					TargetPawn.jobs.EndCurrentJob(JobCondition.Incompletable);
					if (xxx.RomanceDiversifiedIsActive)
					{
						extraSentencePacks.Add(RulePackDef.Named("HookupSucceeded"));
					}
					if (Whore.health.HasHediffsNeedingTend())
					{
						successfulPass = false;
						string key = "RJW_VisitorSickWhore";
						string text = key.Translate(TargetPawn.LabelIndefinite(), Whore.LabelIndefinite()).CapitalizeFirst();
						Messages.Message(text, Whore, MessageTypeDefOf.TaskCompletion);
					}
					else
					{
						string key = "RJW_VisitorAcceptWhore";
						if (Whore.IsPrisoner)
						{
							key = "RJW_VisitorSolicitWhore";
						}
						string text = key.Translate(TargetPawn.LabelIndefinite(), Whore.LabelIndefinite()).CapitalizeFirst();
						Messages.Message(text, TargetPawn, MessageTypeDefOf.TaskCompletion);
					}
				}
				if (!successfulPass)
				{
					// remove bed reservation
					TargetBed.UnreserveForWhoring();

					FleckMaker.ThrowMetaIcon(TargetPawn.Position, TargetPawn.Map, FleckDefOf.IncapIcon);
					TargetPawn.needs.mood.thoughts.memories.TryGainMemory(
						TargetPawn.Faction == Whore.Faction
							? ThoughtDef.Named("RJWTurnedDownWhore")
							: ThoughtDef.Named("RJWFailedSolicitation"), Whore);

					if (xxx.RomanceDiversifiedIsActive)
					{
						Whore.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("RebuffedMyHookupAttempt"), TargetPawn);
						TargetPawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("FailedHookupAttemptOnMe"), Whore);
						extraSentencePacks.Add(RulePackDef.Named("HookupFailed"));
					}
					//Disabled rejection notifications
					//Messages.Message("RJW_VisitorRejectWhore".Translate(new object[] { xxx.get_pawnname(TargetPawn), xxx.get_pawnname(Whore) }), TargetPawn, MessageTypeDefOf.SilentInput);
				}
				if (xxx.RomanceDiversifiedIsActive)
				{
					Find.PlayLog.Add(new PlayLogEntry_Interaction(DefDatabase<InteractionDef>.GetNamed("TriedHookupWith"), pawn, TargetPawn, extraSentencePacks));
				}
				//Log.Message("[RJW] AwaitResponse initAction - successfulPass: " + successfulPass.ToString());
			};
			yield return AwaitResponse;

			Toil BothGoToBed = new Toil();
			BothGoToBed.AddFailCondition(() => !successfulPass || !WhoreBed_Utility.CanUseForWhoring(Whore, TargetBed));
			BothGoToBed.defaultCompleteMode = ToilCompleteMode.Instant;
			BothGoToBed.initAction = delegate
			{
				//ModLog.Message("JobDriver_InvitingVisitors::MakeNewToils - BothGoToBed - initAction is called0");
				if (!successfulPass) return;
				if (!WhoreBed_Utility.CanUseForWhoring(Whore, TargetBed) && Whore.CanReserve(TargetPawn, 1, 0))
				{
					//ModLog.Message("JobDriver_InvitingVisitors::MakeNewToils - BothGoToBed - cannot use the whore bed");
					return;
				}
				//ModLog.Message("JobDriver_InvitingVisitors::MakeNewToils - BothGoToBed - initAction is called1");

				TargetBed.ReserveForWhoring(Whore, 1800);//is 1800 ticks long enough to go to the bed (until next reservation is made?)

				Whore.jobs.jobQueue.EnqueueFirst(JobMaker.MakeJob(xxx.whore_is_serving_visitors, TargetPawn, TargetBed));
				//TargetPawn.jobs.jobQueue.EnqueueFirst(JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WhoreIsServingVisitors"), Whore, TargetBed, (TargetBed.MaxAssignedPawnsCount>1)?TargetBed.GetSleepingSlotPos(1): TargetBed.)), null);
				Whore.jobs.curDriver.EndJobWith(JobCondition.InterruptOptional);
				//TargetPawn.jobs.curDriver.EndJobWith(JobCondition.InterruptOptional);
			};
			yield return BothGoToBed;
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;
using Verse.AI;
//using Multiplayer.API;
using rjw;

namespace rjwwhoring
{
	public class JobDriver_WhoreIsServingVisitors : JobDriver_SexBaseInitiator
	{
		public IntVec3 SleepSpot => Bed.SleepPosOfAssignedPawn(pawn);

		public override bool TryMakePreToilReservations(bool errorOnFailed)
		{
			return pawn.Reserve(Target, job, 1, 0, null, errorOnFailed);
		}

		//[SyncMethod]
		protected override IEnumerable<Toil> MakeNewToils()
		{
			if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":MakeNewToils() - making toils");
			setup_ticks();
			var PartnerJob = xxx.gettin_loved;

			this.FailOnDespawnedOrNull(iTarget);
			this.FailOnDespawnedNullOrForbidden(iBed);

			if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":fail conditions check " + !WhoreBed_Utility.CanUseForWhoring(pawn, Bed) + " " + !pawn.CanReserve(Partner));
			this.FailOn(() => !WhoreBed_Utility.CanUseForWhoring(pawn, Bed) || !pawn.CanReserve(Partner));
			this.FailOn(() => pawn.Drafted);
			this.FailOn(() => Partner.IsFighting());

			yield return Toils_Reserve.Reserve(iTarget, 1, 0);
			int basePrice = WhoringHelper.PriceOfWhore(pawn);
			float bedMult = WhoreBed_Utility.CalculatePriceFactor(Bed);
			//yield return Toils_Reserve.Reserve(BedInd, Bed.SleepingSlotsCount, 0);

			if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":generate job toils");
			Toil gotoBed = new Toil();
			gotoBed.defaultCompleteMode = ToilCompleteMode.PatherArrival;
			gotoBed.FailOnBedNoLongerUsable(iBed, Bed);
			gotoBed.AddFailCondition(() => Partner.Downed);
			gotoBed.FailOn(() => !Partner.CanReach(Bed, PathEndMode.Touch, Danger.Deadly));
			gotoBed.initAction = delegate
			{
				if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":gotoWhoreBed");
				pawn.pather.StartPath(SleepSpot, PathEndMode.OnCell);
				Partner.jobs.StopAll();
				Job job = JobMaker.MakeJob(JobDefOf.GotoMindControlled, SleepSpot);
				Partner.jobs.StartJob(job, JobCondition.InterruptForced);
			};
			yield return gotoBed;

			ticks_left = (int)(2000.0f * Rand.Range(0.30f, 1.30f));

			Toil waitInBed = new Toil();
			waitInBed.initAction = delegate
			{
				ticksLeftThisToil = 5000;
			};
			waitInBed.tickAction = delegate
			{
				pawn.GainComfortFromCellIfPossible();
				if (IsInOrByBed(Bed, Partner) && pawn.PositionHeld == Partner.PositionHeld)
				{
					ReadyForNextToil();
				}
			};
			waitInBed.defaultCompleteMode = ToilCompleteMode.Delay;
			yield return waitInBed;

			Toil StartPartnerJob = new Toil();
			StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant;
			StartPartnerJob.socialMode = RandomSocialMode.Off;
			StartPartnerJob.initAction = delegate
			{
				if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":StartPartnerJob");
				var gettin_loved = JobMaker.MakeJob(PartnerJob, pawn, Bed);
				Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced);
			};
			yield return StartPartnerJob;

			Toil SexToil = new Toil();
			SexToil.defaultCompleteMode = ToilCompleteMode.Never;
			SexToil.socialMode = RandomSocialMode.Off;
			SexToil.handlingFacing = true;
			SexToil.FailOn(() => Partner.Dead);
			SexToil.FailOn(() => Partner.CurJob.def != PartnerJob);
			SexToil.initAction = delegate
			{
				if (WhoringBase.DebugWhoring) ModLog.Message("" + this.GetType().ToString() + ":SexToil start");

				// refresh bed reservation
				Bed.ReserveForWhoring(pawn, ticks_left+100);

				Start();

				// TODO: replace this quick n dirty way
				CondomUtility.GetCondomFromRoom(pawn);
				// Try to use whore's condom first, then client's
				Sexprops.usedCondom = CondomUtility.TryUseCondom(pawn) || CondomUtility.TryUseCondom(Partner);

				if (!RJWSettings.HippieMode && xxx.HasNonPolyPartner(Partner, true))
				{
					Pawn lover = LovePartnerRelationUtility.ExistingLovePartner(Partner);
					// We have to do a few other checks because the pawn might have multiple lovers and ExistingLovePartner() might return the wrong one
					if (lover != null && pawn != lover && !lover.Dead && (lover.Map == Partner.Map || Rand.Value < 0.25) && GenSight.LineOfSight(lover.Position, Partner.Position, lover.Map))
					{
						lover.needs.mood.thoughts.memories.TryGainMemory(RimWorld.ThoughtDefOf.CheatedOnMe, Partner);
					}
				}
			};
			SexToil.AddPreTickAction(delegate
			{
				if (pawn.IsHashIntervalTick(ticks_between_hearts))
					if (xxx.is_nympho(pawn))
						FleckMaker.ThrowMetaIcon(pawn.Position, pawn.Map, FleckDefOf.Heart);
					else
						FleckMaker.ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart);
				SexTick(pawn, Partner);
				SexUtility.reduce_rest(Partner, 1);
				SexUtility.reduce_rest(pawn, 2);
				if (ticks_left % 100 == 0)
					Bed.ReserveForWhoring(pawn, ticks_left + 100); // without this, reservation sometimes expires before sex is finished
				if (ticks_left <= 0)
					ReadyForNextToil();
			});
			SexToil.AddFinishAction(delegate
			{
				End();
			});
			yield return SexToil;

			Toil afterSex = new Toil
			{
				initAction = delegate
				{
					// Adding interactions, social logs, etc
					SexUtility.ProcessSex(Sexprops);

					Bed.UnreserveForWhoring();

					if (!(Partner.IsColonist && (pawn.IsPrisonerOfColony || pawn.IsColonist)))
					{
						int netPrice = (int) (basePrice * bedMult);
						if (netPrice == 0)
							netPrice += 1;

						int bedTip = netPrice - basePrice;
						int defect = WhoringHelper.PayPriceToWhore(Partner, netPrice, pawn);

						if (WhoringBase.DebugWhoring)
						{
							ModLog.Message($"{GetType()}:afterSex toil - {Partner} tried to pay {basePrice}(whore price) + {bedTip}(room modifier) silver to {pawn}");

							if (defect <= 0)
								ModLog.Message(" Paid full price");
							else if (defect <= bedTip)
								ModLog.Message(" Could not pay full tip");
							else
								ModLog.Message(" Failed to pay base price");
						}

						WhoringHelper.UpdateRecords(pawn, netPrice - defect);
					}

					if (SexUtility.ConsiderCleaning(pawn))
					{
						LocalTargetInfo cum = pawn.PositionHeld.GetFirstThing<Filth>(pawn.Map);

						Job clean = JobMaker.MakeJob(JobDefOf.Clean);
						clean.AddQueuedTarget(TargetIndex.A, cum);

						pawn.jobs.jobQueue.EnqueueFirst(clean);
					}
				},
				defaultCompleteMode = ToilCompleteMode.Instant
			};
			yield return afterSex;
		}
	}
}