1
0

16 Коммитууд 125f830d73 ... c09ca91661

Эзэн SHA1 Мессеж Огноо
  R c09ca91661 [fix] Typo. 1 жил өмнө
  hornguy6 497612dd8a [fixed] wrong image calls 1 жил өмнө
  hornguy6 cca27ad4b9 [fixed] blank screen issue maybe 1 жил өмнө
  hornguy6 dcde523674 [fixed] pcs_lovers to pcs_lover 1 жил өмнө
  hornguy6 1d003681cd [fixed] wrong description was showing for rough missionary sex 1 жил өмнө
  hornguy6 8a059cd7b4 [added] saveupdater for the most important variable 1 жил өмнө
  hornguy6 d3d716467a [fixed] more missing variables 1 жил өмнө
  hornguy6 a013050e74 [fixed] many missing variables causing content reliant on them to bug the fuck out - blame_hornguy6 1 жил өмнө
  Kevin_Smarts 7b07db81d0 [added] generic reactions for cool kid chats at school 1 жил өмнө
  Kevin_Smarts efc9001bcb [fixed] location type not set so theme was overwritten when entering hallway from outside 1 жил өмнө
  hornguy6 898a5fd712 [fixed] girlfriends are not going away after you break up with them 1 жил өмнө
  Kevin_Smarts c86c196faa [fixed] separaters for money that will work at higher values as well as it does at lower ones 1 жил өмнө
  netuttki af0e38fbc7 CLeanup 1 жил өмнө
  Kevin_Smarts 7cc91767b0 [fixed] If hypno to stop wearing underwear is in effect Sveta will remove them from the save sets as she goes to wear them 1 жил өмнө
  netuttki 6c06615c7a A guide to the `callvalidator.py`. URL in description 1 жил өмнө
  netuttki 655c5332db Small improvement to `callvalidator.py`. See guide. 1 жил өмнө

+ 11 - 7
locations/agentned.qsrc

@@ -363,14 +363,18 @@ end
 if $ARGS[0] = 'format_price_string':
 	$worknum = STR(ARGS[1])
 	worknumlength = LEN($worknum)
-	pos1 = 1 &
-	pos2 = iif((worknumlength MOD 3) = 0, 3, worknumlength MOD 3)
+	pos1 = 1
 	:format_price_string_loop
-		$split = $MID($worknum, pos1, pos2)
-		$result += iif(pos2 < worknumlength, $split+',', $split)
-		pos1 = pos2+1
-		pos2 = pos1+2
+		$split = $MID($worknum, pos1, 1)
+		if (worknumlength - 1)/3 ! (worknumlength-2)/3:
+			$result += $split+','
+		else
+			$result += $split
+		end
+		worknumlength -= 1
+		pos1 += 1
 	if pos2 <= worknumlength: jump 'format_price_string_loop'
 	killvar 'pos1' & killvar 'pos2' & killvar 'worknum' & killvar 'worknumlength' & killvar 'split'
 end
---- agentned ---------------------------------
+--- agentned ---------------------------------
+

+ 1 - 1
locations/audition_sex2.qsrc

@@ -1139,7 +1139,7 @@ if $ARGS[0] = 'neutral_virgin2':
 	if audition['virgin_know'] = 1:
 		'You wince at the first thrust, feeling his cock tear through your hymen and stretch your virgin walls. And he immediately thrusts again causing you to gasp. And again. And again.'
 	else
-		'You wince at the first thrust, feeling his cock tear through your hymen and stretch your virgin walls. He pauses for a moment. "Was that... are you a virgin?" You don''t answser him, teeth still grit in pain and he looks down at the trickle of blood running down your thigh. "Heh. Well looks like you <i>were</i> a virgin." And he immediately thrusts again causing you to gasp. And again. And again.'
+		'You wince at the first thrust, feeling his cock tear through your hymen and stretch your virgin walls. He pauses for a moment. "Was that... are you a virgin?" You don''t answer him, teeth still grit in pain and he looks down at the trickle of blood running down your thigh. "Heh. Well looks like you <i>were</i> a virgin." And he immediately thrusts again causing you to gasp. And again. And again.'
 	end
 	
 	act'Continue':

+ 7 - 3
locations/boy_updater.qsrc

@@ -34,7 +34,7 @@ end
 
 if $ARGS[0] = 'dick_update':
 	if $npc_dick_desc[$boy] = '':
-		if npc_dick[$boy] < 9:
+		if npc_dick[$boy] < 10:
 			if $npc_thdick[$boy] = 'skinny' or $npc_thdick[$boy] = 'slim':
 				$npc_dick_desc[$boy] = 'tiny'
 			elseif $npc_thdick[$boy] = 'well proportioned' or $npc_thdick[$boy] = 'thicker than average':
@@ -42,7 +42,7 @@ if $ARGS[0] = 'dick_update':
 			elseif $npc_thdick[$boy] = 'thick' or $npc_thdick[$boy] = 'massive' or $npc_thdick[$boy] = 'monstrous':
 				$npc_dick_desc[$boy] = 'chode'
 			end
-		elseif npc_dick[$boy] < 20:
+		elseif npc_dick[$boy] < 16:
 			if $npc_thdick[$boy] = 'skinny' or $npc_thdick[$boy] = 'slim':
 				$npc_dick_desc[$boy] = 'skinny'
 			elseif $npc_thdick[$boy] = 'well proportioned' or $npc_thdick[$boy] = 'thicker than average':
@@ -50,7 +50,7 @@ if $ARGS[0] = 'dick_update':
 			elseif $npc_thdick[$boy] = 'thick' or $npc_thdick[$boy] = 'massive' or $npc_thdick[$boy] = 'monstrous':
 				$npc_dick_desc[$boy] = 'thick'
 			end
-		elseif npc_dick[$boy] < 31:
+		elseif npc_dick[$boy] < 20:
 			if $npc_thdick[$boy] = 'skinny' or $npc_thdick[$boy] = 'slim':
 				$npc_dick_desc[$boy] = 'long'
 			elseif $npc_thdick[$boy] = 'well proportioned' or $npc_thdick[$boy] = 'thicker than average':
@@ -71,4 +71,8 @@ if $ARGS[0] = 'dick_update':
 	end
 end
 
+if $ARGS[0] = 'stamina_update':
+	if npc_sex_stamina[$boy] = 0: npc_sex_stamina[$boy] = rand(1,10)
+end
+
 --- boy_updater ---------------------------------

+ 40 - 1
locations/gschool_coolkid_chats.qsrc

@@ -36,6 +36,7 @@ if $ARGS[0] = 'dimka':
 			act 'Go with Dimka': gt 'gschool_coolkid_chats', 'dimka_sex'
 		end
 	else
+		gs 'npc_reactions', 1
 		if DimaRudeQW > 0 and DimaRudeBlock = 0:
 			'Dimka looks into your eyes with a disinterested glare. "Whatever. After school, we''re going to my place. I''ll wait for you by the entrance."'
 		else
@@ -223,6 +224,7 @@ if $ARGS[0] = 'igor':
 	act 'Time for the next class': gt 'gschool_lessons', 'short_break'
 	if IgorLoverQW > 0:
 		'When Igor sees you, his face lights up and he smiles warmly. "I was hoping I''d see you. I, uh, kind of missed you..." he says shyly and it makes you giggle. While you talk with each other, his warm hand finds yours.'
+		gs 'npc_reactions', 4
 		act 'Help with homework':
 			*clr & cla
 			igor_history = 1
@@ -288,6 +290,7 @@ if $ARGS[0] = 'igor':
 			end
 		end
 	elseif grupTipe = 1:
+		gs 'npc_reactions', 4
 		if npc_rel['A4'] >= 50:
 			if npc_rel['A4'] >= 60 and hotcat >= 5 and IgorQW['house_open'] = 0:
 				IgorQW['house_open'] = 1
@@ -327,6 +330,7 @@ if $ARGS[0] = 'igor':
 			end
 		end
 	elseif grupTipe = 2:
+		gs 'npc_reactions', 4
 		if npc_rel['A4'] >= 50:
 			if npc_rel['A4'] >= 60 and hotcat >= 5 and IgorQW['house_open'] = 0:
 				IgorQW['house_open'] = 1
@@ -366,6 +370,7 @@ if $ARGS[0] = 'igor':
 			end
 		end
 	elseif grupTipe = 3:
+		gs 'npc_reactions', 4
 		if npc_rel['A4'] >= 50:
 			if npc_rel['A4'] >= 60 and hotcat >= 5 and IgorQW['house_open'] = 0:
 				IgorQW['house_open'] = 1
@@ -405,6 +410,7 @@ if $ARGS[0] = 'igor':
 			end
 		end
 	elseif grupTipe = 4:
+		gs 'npc_reactions', 4
 		if npc_rel['A4'] >= 70:
 			if npc_rel['A4'] >= 75 and hotcat >= 5 and IgorQW['house_open'] = 0:
 				IgorQW['house_open'] = 1
@@ -438,6 +444,7 @@ if $ARGS[0] = 'igor':
 		if npc_rel['A4'] >= 80:
 			'"Hey Igor, what are you doing?" you ask as you see him looking around for someone.'
 			'He shrugs dismissively. "Just waiting for Dimka."'
+			gs 'npc_reactions', 4
 			'The two of you spend some time chatting while he waits for Dimka. Eventually he shows up and Igor is ready to leave. "Maybe we can talk some other time?" he asks with a small smile as he waves goodbye.'
 			act 'Help with homework':
 				*clr & cla
@@ -580,6 +587,7 @@ if $ARGS[0] = 'katja':
 				'Katja''s face is flushed bright red and her chest is heaving from her heavy breathing. She''s idly rubbing her thighs against one another while you talk.'
 			end
 		end
+		gs 'npc_reactions', 14
 		if katjaQW['drunk_help'] = 1:
 			act 'Thank her for taking you home':
 				*clr & cla
@@ -897,6 +905,7 @@ if $ARGS[0] = 'bella':
 			'"Ugh," you sigh. "That''s a long story for another time."'
 			'"Okay, no hurry." she assures you.'  
 		end
+		gs 'npc_reactions', 22
 	elseif grupTipe = 3:
 		if npc_rel['A22'] >= 70:
 			'You see Bella waving at you to get your attention. "Hey <<$pcs_nickname>>, can I take a quick look at your notes for the next class, thanks." She takes your notebook before you can even answer.'
@@ -918,6 +927,7 @@ if $ARGS[0] = 'bella':
 			'You try to talk to her a bit more, but she mostly ignores you. When the bell rings and you both go your own ways, she taps your shoulder. "The Phantom Menace is the best."'
 			'"Wait, how do you...?" You only get a sly wink as an answer.'
 		end
+		gs 'npc_reactions', 22
 	elseif grupTipe = 4:
 		if npc_rel['A22'] >= 70:
 			'You brashly squeeze yourself between Bella and her friends, who all lighten up when you start sharing stories of the petty crimes and practical jokes the gopniks have been performing.'
@@ -934,8 +944,10 @@ if $ARGS[0] = 'bella':
 			'"Bitch, do I look like a drug dealer to you?" you answer sternly and suggest she try her luck with Vitek.' 
 			'"Fine, I will!" The two of you talk a bit more, but it isn''t a comfortable conversation.'
 		end
+		gs 'npc_reactions', 22
 	else
 		if npc_rel['A22'] >= 70:
+			gs 'npc_reactions', 22
 			'"You know, you should come and hang out with me and my friends," Bella says with a smile.'
 			'"You really mean that?!" you ask as your eyes widen. "You think I''ll fit in with them?"'
 			'Bella nods. "No doubt! You''ll have no issues fitting in."' 
@@ -1126,6 +1138,7 @@ if $ARGS[0] = 'lizaveta':
 			'"The current rumor is that you''ve sucked well over 100 dicks!" Lizaveta exclaims with a cruel laugh. "There''s even a bet that you''ll have sucked or fucked 1,000 dicks by the end of the year. Want to know if I''m betting against or for you?" she taunts before dismissing it as a joke, but you''re not sure if she''s telling the truth...'
 		end
 	elseif grupTipe = 1:
+		gs 'npc_reactions', 140
 		if npc_rel['A140'] >= 50:
 			'The perks of being a close friend of Liza go beyond just running in the same social circle. She tells you some gossip that no one else should know about.'
 			'"I heard from a little red bird that one time while Vicky was out partying at the community center, she couldn''t hold it in, so she went to do her business behind a bush, buuuut..." Liza drags it out to build a little suspense. "She was so drunk that she ended up falling into her own piss! Luckily Kat-- her friend, I mean, was there to take her home before anyone saw!"'
@@ -1139,6 +1152,7 @@ if $ARGS[0] = 'lizaveta':
 			act 'Latest gossip': gt 'gschool_coolkid_chats', 'lizaveta_latest_gossip'
 		end
 	elseif grupTipe = 2:
+		gs 'npc_reactions', 140
 		if npc_rel['A140'] >= 50:
 			'You would think that being close friends with Lizaveta would mean getting some exclusive gossip from her, but she keeps her lips sealed. "I know everyone likes to say I can''t keep my mouth shut, but even I need to have some secrets of my own." she winks.'
 			'"Oh come on!" you plead. "You gotta give me a little bit of something..."'
@@ -1151,6 +1165,7 @@ if $ARGS[0] = 'lizaveta':
 			act 'Latest gossip': gt 'gschool_coolkid_chats', 'lizaveta_latest_gossip'
 		end
 	elseif grupTipe = 3:
+		gs 'npc_reactions', 140
 		if npc_rel['A140'] >= 50:
 			'When you sit on the floor next to Lizaveta, she smiles at you and the two of you are soon talking about a variety of subjects. However, she can''t help herself and soon starts asking you all sorts of questions about your fellow nerds. You can barely even get a word in edge wise as she pumps you for gossip. You can''t help yourself and start letting some stuff slip as the two of you talk.'
 			act 'Latest gossip': gt 'gschool_coolkid_chats', 'lizaveta_latest_gossip'
@@ -1160,6 +1175,7 @@ if $ARGS[0] = 'lizaveta':
 			'When you sit on the floor next to Lizaveta, she starts asking you all sorts of questions about your fellow nerds. You can barely get a word in edge wise as she pumps you for gossip. You just can''t help yourself and start letting some stuff slip as the two of you talk.'
 		end
 	elseif grupTipe = 4:
+		gs 'npc_reactions', 140
 		if npc_rel['A140'] >= 50:
 			'When you sit on the floor next to Lizaveta, she smiles at you and the two of you are soon talking about a variety of subjects. However, she can''t help herself and starts asking you all sorts of questions about your fellow gopniks. You can barely even get a word in edge wise as she pumps you for gossip. You can''t help yourself and start letting some stuff slip as the two of you talk.'
 			act 'Latest gossip': gt 'gschool_coolkid_chats', 'lizaveta_latest_gossip'
@@ -1271,6 +1287,7 @@ if $ARGS[0] = 'marcus':
 			'You walk up to Marcus and try to talk to him. He mostly ignores you, with only the occasional "uh-huh" for an answer. You notice the others giving you disgusted looks and he finally speaks up. "Look, I don''t mean to be rude, but we''re not friends and I don''t want to talk to you." You sigh and nod before walking away.'
 		end
 	elseif grupTipe = 1:
+		gs 'npc_reactions', 146
 		if npc_rel['A146'] >= 50:
 			'Talking with Marcus is always fun. He always knows how to make you laugh with the stories he tells. "You should have seen his face!" He lets out a deep laugh. "We walk by the bathroom on the way to his room and BAM! There''s his mom, butt naked, and we see it all! You ever seen someone change colors? Poor guy was as pink as... as his mom''s nipples now that I think about it!"'
 			'You spend the rest of break laughing along with him as he tells you some more stories.'
@@ -1287,6 +1304,7 @@ if $ARGS[0] = 'marcus':
 		else
 			'You walk up to Marcus and he gives you a smile as you start talking to him. The conversation quickly turns to sports, mostly sports in America. It seems he was a jock back home and loves watching and playing sports. He seems to really miss American football, his favorite sport to play, but is happy there is basketball here, his second favorite sport. He talks about the games he played back home.'
 		end
+		gs 'npc_reactions', 146
 	elseif grupTipe = 3:
 		if npc_rel['A146'] >= 50:
 			'You walk up to Marcus and he gives you a smile as you start talking to him. You enjoy hearing the stories Marcus tells about his life in America, though he often talks about the differences between nerds here and there. He explains how nerds back home are less about grades and more about what school club you belonged to.'
@@ -1297,6 +1315,7 @@ if $ARGS[0] = 'marcus':
 			'You walk up to Marcus and he gives you a smile as you start talking to him. You enjoy hearing the stories Marcus tells about his life in America. "It''s kind of funny, I don''t think I was nearly as popular as this back home. I''m not complaining though!"'
 			'You spend the rest of break asking more questions about his home life and he''s happy to tell you all about it.'
 		end
+		gs 'npc_reactions', 146
 	elseif grupTipe = 4:
 		if npc_rel['A146'] >= 50:
 			'You walk up to Marcus and he gives you a smile as you start talking to him. You enjoy hearing the stories Marcus tells about his life in America. "You guys seem a lot more fun than I expected. I''m still trying to wrap my head around what a gopnik is. I know a lot of you are called that, but there are some big differences." You explain some of the differences between the collective term and what a real gopnik is, which just leads to him once again wondering why you all hang out together.'
@@ -1305,6 +1324,7 @@ if $ARGS[0] = 'marcus':
 		else
 			'You walk up to Marcus and he gives you a smile as you start talking to him. You enjoy hearing the stories Marcus tells about his life in America. "You guys aren''t nearly as bad as the bangers back home. I''ve never seen any of you carrying guns." He goes on to tell you about some of his encounters with gangbangers back home. It sounds like they were a lot more dangerous than gopniks.'
 		end
+		gs 'npc_reactions', 146
 	else
 		if npc_rel['A146'] >= 50:
 			'You walk up to Marcus and try talking to him, but he mostly ignores you with only the occasional "uh-huh" for an answer. You notice the others giving you disgusted looks before he gets up, gives you a very slight nod and walks away with Andrey.'
@@ -1344,6 +1364,7 @@ if $ARGS[0] = 'andrey':
 			'Andrey glances your way for a second before focusing back on looking through his locker, completely uninterested in you. "Shouldn''t you be in the bathroom with the gopniks sucking them all off?" he remarks before turning away and ignoring you until you leave.'
 		end
 	elseif grupTipe = 1:
+		gs 'npc_reactions', 147
 		if npc_rel['A147'] >= 50:
 			'"Do you think Stasya will ever get over this whole... jealousy thing she has for Marcus?" Andrey confides in you with a look of exhaustion.'
 			'Stasya must really be putting him through it lately. "She''ll get over herself, don''t worry. Just be glad you''re not one of the nerds." you tease.'
@@ -1367,6 +1388,7 @@ if $ARGS[0] = 'andrey':
 			'"Oh yeah?" You can''t help but smile when you see the good mood he''s in. "Did something happen recently?"'
 			'"No, it''s just that hanging around him, he is way more into sports than I am. But he got me into working out and jogging and you know what? I feel great." He goes on talking about the positive changes in his life since Marcus moved in.'
 		end
+		gs 'npc_reactions', 147
 	elseif grupTipe = 3:
 		if npc_rel['A147'] >= 50:
 			'"Hey, Andrey! How''s it been?" you ask with a small smile.'
@@ -1381,6 +1403,7 @@ if $ARGS[0] = 'andrey':
 			'"Hey, Andrey! How''s it been?" you ask with a small smile.'
 			'He gives you a slightly confused look as to why you''re talking to him. "If I wanted to talk to you, I would come find you. Go away." He proceeds to ignore you and you can feel everyone else staring at you. Afraid someone might start picking on you, you quickly leave.'
 		end
+		gs 'npc_reactions', 147
 	elseif grupTipe = 4:
 		if npc_rel['A147'] >= 50:
 			'"Hey, Andrey! How''s it been?" you ask with a small smile.'
@@ -1395,6 +1418,7 @@ if $ARGS[0] = 'andrey':
 			'"Hey, Andrey! How''s it been?" you ask with a small smile.'
 			'He gives you a slightly confused look as to why you''re talking to him. "Why are you talking to me? We''re not friends, so go bother someone else." He proceeds to ignore you and you can feel everyone else staring at you.'
 		end
+		gs 'npc_reactions', 147
 	else
 		gs 'npc_relationship', 'modify', 'A147', 'dislike'
 		'"Hey, Andrey! How''s it been?" you ask with a small smile.'
@@ -1413,7 +1437,7 @@ if $ARGS[0] = 'mefodiy':
 		if npc_rel['A148'] >= 50:
 			'"I hear you''ve been a naughty girl, slutting it up. Someone should give you a spanking, but you''d probably like it. Maybe I could help you there, if we stick to the spanking."'
 			'"Sure you don''t want more?" you tease.'
-			'"I''m sure there''s a lot of guy that''ll take you up on that offer, but it''s not my bag."'
+			'"I''m sure there''s a lot of guys that''ll take you up on that offer, but it''s not my bag."'
 			'You wrap an arm around him and stroke his chest. "Aww, you don''t know what you''re missing."'
 			'"Oh I do, but if by some bizarre act of God I change my preferences, you''ll be the first one I call.'
 		elseif npc_rel['A148'] <= 20:
@@ -1425,6 +1449,7 @@ if $ARGS[0] = 'mefodiy':
 			'"It''s not like I ran an article in the school newspaper! Some guys just don''t know when to keep quiet."'
 			'"Some? More like all of them." You both laugh as he gives you a big and over dramatic hug.'
 		end
+		gs 'npc_reactions', 148
 	elseif grupTipe = 1:
 		if npc_rel['A148'] >= 50:
 			'Hey <<$pcs_nickname>>, how''s it going?'
@@ -1444,6 +1469,7 @@ if $ARGS[0] = 'mefodiy':
 			'"Same here." He puts an arm around you. "A hug''ll make it all better."'
 			'You don''t have much choice but to hug this soppy guy, but it does raise your mood.'
 		end
+		gs 'npc_reactions', 148
 	elseif grupTipe = 2:
 		if npc_rel['A148'] >= 50:
 			'"If it isn''t my favourite jock, what''s up?"'
@@ -1462,6 +1488,7 @@ if $ARGS[0] = 'mefodiy':
 			'He grabs you in a big hug. "Well done champ!"'
 			'You push him off you. "Yeah yeah, very funny."'
 		end
+		gs 'npc_reactions', 148
 	elseif grupTipe = 3:
 		if npc_rel['A148'] >= 50:
 			'"Hi there brainiac, how''s it going?"'
@@ -1476,6 +1503,7 @@ if $ARGS[0] = 'mefodiy':
 			'"Yeah, got to work hard, get a good job and all that."'
 			'"That''s a good plan, just don''t over do it."'
 		end
+		gs 'npc_reactions', 148
 	elseif grupTipe = 4:
 		if npc_rel['A148'] >= 50:
 			'"Hey <<$pcs_nickname>>, still hanging around with those a-holes? You can do better than them."'
@@ -1489,6 +1517,7 @@ if $ARGS[0] = 'mefodiy':
 			'"I don''t want any trouble, so just spit it out."'
 			'"I just want to chat, I''m not here to cause trouble." you reply while holding your hands up.'
 		end
+		gs 'npc_reactions', 148
 	else
 		if npc_rel['A148'] >= 50:
 			'"Hey sweetie, you know I could help you get into a decent social group. You just gotta put a bit of work into it."'
@@ -1500,6 +1529,7 @@ if $ARGS[0] = 'mefodiy':
 			'"Hey there <<$pcs_firstname>>, we gotta get you into a social group. It''ll make everything that bit easier for you."'
 			'"I''m working on it!" He has a point. Life can be tough as an outcast.'
 		end
+		gs 'npc_reactions', 148
 	end
 	act 'Time for the next class': gt 'gschool_lessons', 'short_break'
 end
@@ -1537,6 +1567,7 @@ if $ARGS[0] = 'vicky':
 			'Vicky is silent for a while before shrugging. "No?"'
 			'"Bald. You will definitely be bald after a week of dying your hair..." You and Vicky then spend the rest of break joking back and forth.'
 		end
+		gs 'npc_reactions', 15
 	elseif grupTipe = 2:
 		if npc_rel['A15'] >= 50:
 			'"Hey <<$pcs_nickname>>, I''m working on a new flip for cheerleading and I could use a spotter."'
@@ -1547,6 +1578,7 @@ if $ARGS[0] = 'vicky':
 			'"Hey <<$pcs_nickname>>, I see you''re making a name for yourself. Keep up the good work!" she says as she gives you a high five. "Just remember what a famous person once said, ''Strong women don’t have ''attitudes'', we have standards.''"'
 			'Vicky spends some time talking to you until the end of the break.'
 		end
+		gs 'npc_reactions', 15
 	elseif grupTipe = 3:
 		if npc_rel['A15'] >= 60:
 			'"Hey <<$pcs_nickname>>, can you help me with this Math assignment? It really has me stumped," she says, showing you a page of her homework. You glace over it and point out a few simple mistakes she had made that were messing up her equations. She thanks you for the help and then spends the rest of the time during break talking to you about other things.'
@@ -1557,6 +1589,7 @@ if $ARGS[0] = 'vicky':
 		else
 			'It can be hard to follow Vicky as she keeps up a lively conversation, jumping from one topic to another; but you don''t really mind and find her upbeat attitude intoxicating.'
 		end
+		gs 'npc_reactions', 15
 	elseif grupTipe = 4:
 		if npc_rel['A15'] >= 60:
 			'"Hey <<$pcs_nickname>>, can I ask you a favor? Could you keep an eye on my sister for me? I heard some guys are taking their interest in her too far. I''d like her to open up a bit, but not in the way they have in mind, if you know what I mean."'
@@ -1566,6 +1599,7 @@ if $ARGS[0] = 'vicky':
 		else
 			'It can be hard to follow Vicky as she keeps up a lively conversation, jumping from one topic to another; but you don''t really mind and find her upbeat attitude intoxicating.'
 		end
+		gs 'npc_reactions', 15
 	else
 		if npc_rel['A15'] >= 70:
 			'"I''ve been thinking of going all in and dying my hair to match the color of the outfits I wear. What do you think?" Vicky asks as she runs her fingers through her red hair.'
@@ -1577,6 +1611,7 @@ if $ARGS[0] = 'vicky':
 		else
 			'It can be hard to follow Vicky as she keeps up a lively conversation, jumping from one topic to another; but you don''t really mind and find her upbeat attitude intoxicating.'
 		end
+		gs 'npc_reactions', 15
 	end
 	act 'Time for the next class': gt 'gschool_lessons', 'short_break'
 	if mesec > 0 and isprok = 0 and isprokp = 0:
@@ -1658,6 +1693,7 @@ if $ARGS[0] = 'stasya':
 		else
 			'You spend some time conversing with Stasya until she holds out her hand to stop you from talking. "I don''t mean to cut you off, but I need to get see Andrey before break ends." She gives you a half-assed apologetic smile before walking off in search of her elusive boyfriend.'
 		end
+		gs 'npc_reactions', 139
 	elseif grupTipe = 2:
 		if npc_rel['A139'] >= 50:
 			'As you walk up, Stasya gives her reflection in the little mirror hanging inside her locker one last look and asks Bella what she thinks of her lipstick.'
@@ -1676,6 +1712,7 @@ if $ARGS[0] = 'stasya':
 		else
 			'She stares at you approaching. "What do you want? Never mind I don''t want to know." She turns and ignores you, talking with Bella and Irina instead, who also ignore you. At least they don''t chase you off.'
 		end
+		gs 'npc_reactions', 139
 	elseif grupTipe = 4:
 		if npc_rel['A139'] >= 50:
 			'She looks you over from head to toe before she scoffs. "What?"'
@@ -1844,6 +1881,7 @@ if $ARGS[0] = 'irina':
 			'"You don’t have any friends, do you?" Irina asks with a stern, unimpressed look. "And you won''t ever find any either." She then turns around and ignores you.'
 		end
 	end
+	gs 'npc_reactions', 17
 	act 'Time for the next class': gt 'gschool_lessons', 'short_break'
 	if mesec > 0 and isprok = 0 and isprokp = 0:
 		act'Ask for a tampon':
@@ -2010,6 +2048,7 @@ if $ARGS[0] = 'sonia':
 			'You spend some time talking with Sonia, but she ends up focusing more on the magazine she''s reading, which is a bit disappointing, but at least she stuck around.'
 		end
 	end
+	gs 'npc_reactions', 25
 	act 'Time for the next class': gt 'gschool_lessons', 'short_break'
 	if mesec > 0 and isprok = 0 and isprokp = 0:
 		act 'Ask for a tampon':

+ 1 - 0
locations/korrPar.qsrc

@@ -18,6 +18,7 @@ boycherdaksex = 0
 minut += 1
 bonusZ = 0
 display_bb = 0
+$location_type = 'private'
 gs 'themes', 'indoors'
 gs 'family_schedule'
 gs 'stat'

+ 1 - 0
locations/lover.qsrc

@@ -131,6 +131,7 @@ if $ARGS[0] = 'remove':
 
 	killvar 'pcs_lovers', i
 	pcs_lover -=1
+	if loverGender[i] = 1: pcs_girlfriends -= 1
 end
 
 if $ARGS[0] = 'add fuckbuddy':

+ 312 - 91
locations/npcgeneratec.qsrc

@@ -164,7 +164,7 @@ if npc_dick[$npclastgenerated] < 9:
 	end
 	
 !! average length dicks
-elseif npc_dick[$npclastgenerated] < 20:
+elseif npc_dick[$npclastgenerated] < 13:
 	if $npc_thdick[$npclastgenerated] = 'skinny' or $npc_thdick[$npclastgenerated] = 'slim':
 	
 		$npc_dick_desc[$npclastgenerated] = 'skinny'
@@ -179,7 +179,7 @@ elseif npc_dick[$npclastgenerated] < 20:
 		
 	end
 !! long dicks
-elseif npc_dick[$npclastgenerated] < 31:
+elseif npc_dick[$npclastgenerated] < 18:
 	if $npc_thdick[$npclastgenerated] = 'skinny' or $npc_thdick[$npclastgenerated] = 'slim':
 	
 		$npc_dick_desc[$npclastgenerated] = 'long'
@@ -296,16 +296,20 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 !!	occupation set, list below
 
 	npc_residence[$npclastgenerated] = temp_location
-
-	if temp_location = 1:
+	if npc_residence[$npclastgenerated] = 1:
 		npc_finance[$npclastgenerated] = 0
-	elseif temp_location = 2:
+		$npc_residence[$npclastgenerated] = 'pav_res'
+	elseif npc_residence[$npclastgenerated] = 2:
 		npc_finance[$npclastgenerated] = 0
-	elseif temp_location = 3:
+		$npc_residence[$npclastgenerated] = 'student_dorms'
+	elseif npc_residence[$npclastgenerated] = 2:
 		npc_finance[$npclastgenerated] = rand(1,2)
-	elseif temp_location = 4:
+		$npc_residence[$npclastgenerated] = 'city_res'
+	elseif npc_residence[$npclastgenerated] = 2:
 		npc_finance[$npclastgenerated] = 2
+		$npc_residence[$npclastgenerated] = 'city_center'
 	end
+
 	
 	if npc_finance[$npclastgenerated] = 0:
 		if npc_residence[$npclastgenerated] ! 1 and npc_residence[$npclastgenerated] ! 4 and npctempgage < 22:
@@ -319,14 +323,24 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 		end
 		npc_occupation[$npclastgenerated] = rand(1,7)
 		if rand(1,3) = 1:
-			npc_start_free_time[$npclastgenerated] = 9
+			npc_start_free_time[$npclastgenerated] = 8
 			npc_end_free_time[$npclastgenerated] = 12
+			
+			npc_work_start[$npclastgenerated] = 13
+			npc_work_end[$npclastgenerated] = 21
+			
 		elseif rand(1,2) = 1:
-			npc_start_free_time[$npclastgenerated] = 16
+			npc_start_free_time[$npclastgenerated] = 15
 			npc_end_free_time[$npclastgenerated] = 20
+			
+			npc_work_start[$npclastgenerated] = 6
+			npc_work_end[$npclastgenerated] = 14
 		else
-			npc_start_free_time[$npclastgenerated] = 20
-			npc_end_free_time[$npclastgenerated] = 23
+			npc_start_free_time[$npclastgenerated] = 18
+			npc_end_free_time[$npclastgenerated] = 22
+			
+			npc_work_start[$npclastgenerated] = 9
+			npc_work_end[$npclastgenerated] = 17
 		end
 		npc_day_off[$npclastgenerated] = rand(1,7)
 	elseif npc_finance[$npclastgenerated] = 1:
@@ -334,14 +348,20 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 		npc_occupation[$npclastgenerated] = rand(7,15)
 		
 		if rand(1,2) = 1:
-			npc_start_free_time[$npclastgenerated] = 9
+			npc_start_free_time[$npclastgenerated] = 8
 			npc_end_free_time[$npclastgenerated] = 12
+			
+			npc_work_start[$npclastgenerated] = 13
+			npc_work_end[$npclastgenerated] = 21
 		else
-			npc_start_free_time[$npclastgenerated] = 20
-			npc_end_free_time[$npclastgenerated] = 23
+			npc_start_free_time[$npclastgenerated] = 18
+			npc_end_free_time[$npclastgenerated] = 22
+			
+			npc_work_start[$npclastgenerated] = 9
+			npc_work_end[$npclastgenerated] = 17
 		end
 		
-		npc_car[$npclastgenerated] = rand(-3,1)
+		if npc_car[$npclastgenerated] = 0: npc_car[$npclastgenerated] = rand(-3,1)
 	elseif npc_finance[$npclastgenerated] = 2:
 		npc_apt_type[$npclastgenerated] = 5
 		!!npc_apt_type[$npclastgenerated] = rand(5,6)
@@ -453,6 +473,7 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 		$npc_occupation[$npclastgenerated] = 'fast_food'
 	elseif npc_occupation[$npclastgenerated] = 6: 
 		$npc_occupation[$npclastgenerated] = 'taxi_driver'
+		npc_car[$npclastgenerated] = 1
 	elseif npc_occupation[$npclastgenerated] = 7: 
 		$npc_occupation[$npclastgenerated] = 'masseuse'
 	elseif npc_occupation[$npclastgenerated] = 8: 
@@ -468,74 +489,37 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 	elseif npc_occupation[$npclastgenerated] = 13: 
 		$npc_occupation[$npclastgenerated] = 'waiter'
 	elseif npc_occupation[$npclastgenerated] = 14: 
-		$npc_occupation[$npclastgenerated] = 'personal trainer'
+		$npc_occupation[$npclastgenerated] = 'personal_trainer'
 	elseif npc_occupation[$npclastgenerated] = 15: 
 		$npc_occupation[$npclastgenerated] = 'programmer'
 	elseif npc_occupation[$npclastgenerated] = 16: 
-		$npc_occupation[$npclastgenerated] = 'businessman'
+		$npc_occupation[$npclastgenerated] = 'criminal'
+		!! npc_criminal_open determines whether or not they will hide their criminality from the player
+		npc_criminal_open[$npclastgenerated] = rand(0,1)
+		if rand(1,3) = 1:
+			$npc_crime_type[$npclastgenerated] = 'drug_dealer'
+		elseif rand(1,2) = 1:
+			$npc_crime_type[$npclastgenerated] = 'enforcer'
+		else
+			$npc_crime_type[$npclastgenerated] = 'thief'
+		end
 	elseif npc_occupation[$npclastgenerated] = 17: 
-		$npc_occupation[$npclastgenerated] = 'lawyer'
+		$npc_occupation[$npclastgenerated] = 'businessman'
 	elseif npc_occupation[$npclastgenerated] = 18: 
-		$npc_occupation[$npclastgenerated] = 'investment banker'
+		$npc_occupation[$npclastgenerated] = 'lawyer'
+	elseif npc_occupation[$npclastgenerated] = 19: 
+		$npc_occupation[$npclastgenerated] = 'investment_banker'
 	end
 
-!!	type of homour
-	npc_humor[$npclastgenerated] = rand(0,3)
-	
-!! Preferred sexual position
-	npc_fav_pos[$npclastgenerated] = rand(1,7)
 	
-	if npc_fav_pos[$npclastgenerated] = 1:
-		$npc_fav_pos[$npclastgenerated] = 'missionary'
-	elseif npc_fav_pos[$npclastgenerated] = 2:
-		$npc_fav_pos[$npclastgenerated] = 'doggy'
-	elseif npc_fav_pos[$npclastgenerated] = 3:
-		$npc_fav_pos[$npclastgenerated] = 'cowgirl'
-	elseif npc_fav_pos[$npclastgenerated] = 4:
-		$npc_fav_pos[$npclastgenerated] = 'blowjob'
-	elseif npc_fav_pos[$npclastgenerated] = 5:
-		$npc_fav_pos[$npclastgenerated] = 'titjob'
-	elseif npc_fav_pos[$npclastgenerated] = 6:
-		$npc_fav_pos[$npclastgenerated] = '69'
-	elseif npc_fav_pos[$npclastgenerated] = 7:
-		$npc_fav_pos[$npclastgenerated] = 'anal'
-	end
-	
-	!! npc_sex_speed determines whether they like it slow, steady, or fast and will cause them to select that speed more frequently
-	!! 1 is slow, 2 is steady, 3 is fast/rough
-	npc_sex_speed[$npclastgenerated] = rand(1,3)
+!! ------------------------- lifestyle and personality choices ----------------------------------
 
-!! Preferred cumming location
-!!	0 = no preference
-	npc_cum_pref[$npclastgenerated] = rand(0,5)
-	
-	if npc_cum_pref[$npclastgenerated] = 1:
-		$npc_cum_pref[$npclastgenerated] = 'creampie'
-	elseif npc_cum_pref[$npclastgenerated] = 2:
-		$npc_cum_pref[$npclastgenerated] = 'mouth'
-	elseif npc_cum_pref[$npclastgenerated] = 3:
-		$npc_cum_pref[$npclastgenerated] = 'facial'
-	elseif npc_cum_pref[$npclastgenerated] = 4:
-		$npc_cum_pref[$npclastgenerated] = 'tits'
-	elseif npc_cum_pref[$npclastgenerated] = 5:
-		$npc_cum_pref[$npclastgenerated] = 'pullout'
-	end
-	
 
-!!	npc_tit_pref determines an npcs preference for breast size
-!!	if npc_tit_pref = 0: they don''t care
-!!	if npc_tit_pref = 1: they like small tits (A or smaller)
-!!	if npc_tit_pref = 2: they like medium sized tits (B to C)
-!!	if npc_tit_pref = 3: they like busty girls (D to E)
-!!	if npc_tit_pref = 4: they like big fat titties (F+)
-	npc_tit_pref[$npclastgenerated] = rand(0,4)
-	
-!!	npc_bush_pref determines an npcs preference for the player''s shaving habits
-!!	if npc_bush_pref = 0: they don''t care
-!!	if npc_bush_pref = 1: they prefer it cleanshaven
-!!	if npc_bush_pref = 2: they like it trimmed or cleanshaven
-!!	if npc_bush_pref = 3: they like it bushy
-	npc_bush_pref[$npclastgenerated] = rand(0,3)
+!!	type of humour
+!!	1 - childish
+!!	2 - perverted
+!!	3 - intellectual/clever
+	npc_humor[$npclastgenerated] = rand(0,3)
 
 !! 	if npc_smoker > 0: they smoke cigarettes
 	npc_smoker[$npclastgenerated] = rand(0,2)
@@ -549,10 +533,15 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 !! we will skip addit for now, have a variable just for smoking
 !!	npc_addit[$npclastgenerated] = rand(0,1)
 
-!!	if npc_doors = 0: they have no preference on indoor or outdoor
-!!	if npc_doors = 1: they like outdoor activities
-!!	if npc_doors = 2: they like indoor activities
-	npc_doors[$npclastgenerated] = rand(0,2)
+	npc_door_pref[$npclastgenerated] = rand(0,2)
+	if npc_door_pref[$npclastgenerated] = 1:
+		!! they like going out for things and doing things outside
+		$npc_door_pref[$npclastgenerated] = 'outdoor'
+	elseif npc_door_pref[$npclastgenerated] = 2: 
+		!! they like more quiet activities and staying at home
+		$npc_door_pref[$npclastgenerated] = 'indoor'
+	end
+	
 	
 !!	npc_goal is what they want out of a relationship
 !!	1 = just sex 
@@ -611,46 +600,211 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 		end
 	end
 	
+	if rand(0,2) > 0:
+		if rand(0,1) = 1:
+			npc_neat[$npclastgenerated] = 1
+			npc_messy[$npclastgenerated] = 0
+		else
+			npc_messy[$npclastgenerated] = 1
+			npc_neat[$npclastgenerated] = 0
+		end
+	end
 	
-	!! if npc_argumentative = 1:, they will get into more arguments with you about things
+	!! npc_gentle = 1: npc is likely to have a soft emotional and physical touch outside of sex
+	!! npc_rough = 1: npc is likely to have a rough/aggressive emotional and physical touch outside of sex
+	if rand(0,2) > 0:
+		if rand(0,1) = 1:
+			npc_gentle[$npclastgenerated] = 1
+			npc_rough[$npclastgenerated] = 0
+		else
+			npc_gentle[$npclastgenerated] = 1
+			npc_rough[$npclastgenerated] = 0
+		end
+	end
+	!! npc_diligent = 1: npc is more methodical, doesn''t like to skip steps, and usuallly plays it safe
+	!! npc_risktaker = 1: npc is more likely to take risks, such as never using a condom
+	if rand(0,2) > 0:
+		if rand(0,1) = 1:
+			npc_diligent[$npclastgenerated] = 1
+			npc_risktaker[$npclastgenerated] = 0
+		else
+			npc_diligent[$npclastgenerated] = 1
+			npc_risktaker[$npclastgenerated] = 0
+		end
+	end
+	
+	!! if npc_argumentative = 1: they will get into more arguments with you about things
 	!! it is also harder to persuade them
 	npc_argumentative[$npclastgenerated] = rand(0,2)
 	
+	!! if npc_assertive = 1: they will know what they want
+	!! if npc_assertive = -1: they will often ask what the player wants
+	!! it is also harder to persuade them
+	npc_assertive[$npclastgenerated] = rand(-1,1)
+	
 	!! how easy or difficult it is to persuade them into doing something
 	npc_willpwr[$npclastgenerated] = rand(1,50)
 	npc_willpwr[$npclastgenerated] += npc_argumentative[$npclastgenerated] * 10
 	
+	!! if npc_arrogant = 1: they will act arrogantly
+	npc_arrogant[$npclastgenerated] = rand(-1,1)
+	
 	!! if npc_competitive = 1: they are overly competitive in contests against you or others
 	npc_competitive[$npclastgenerated] = rand(-1,1)
 	
+	
 	!! if npc_insecure = 1: they are insecure in their masculinity and won''t respond well to teasing
 	npc_insecure[$npclastgenerated] = rand(-1,1)
 	
-	if rand(0,1) = 1:
+	!! if npc_gymrat = 1: they like working out
+	npc_gymrat[$npclastgenerated] = rand(-1,1)
+	
+	!! if npc_abusive = 1: the npc will be abusive
+	npc_abusive[$npclastgenerated] = rand(-3,1)
+	
+	
+	!! if npc_caretaker = 1: they will frequently show love through acts of service
+	!! example: making you breakfast in bed
+	if npc_selfish[$npclastgenerated] ! 1: npc_caretaker[$npclastgenerated] = rand(-3,1)
+	
+!! ------------------------- sex related preferences ----------------------------------
+
+	if rand(0,1) >= 1 and npc_risktaker[$npclastgenerated] = 1:
 !!		if npc_condom_conscious = 1: they will use condoms but can be talked out of it
 !!		if npc_condom_conscious = 2: they will always insist on using condoms unless you are in a committed relationship 
-		npc_condom_conscious[$npclastgenerated] = rand(-2,2)
-	else
+		if npc_diligent[$npclastgenerated] = 1:
+			npc_condom_conscious[$npclastgenerated] = rand(-1,2)
+		else
+			npc_condom_conscious[$npclastgenerated] = rand(-2,2)
+		end
+	elseif npc_diligent[$npclastgenerated] ! 1:
 !!		if npc_no_condoms = 1: they have a preference for skipping condoms but can be talked into using one
 !!		if npc_no_condoms = 2: they will never use a condom no matter what
-		npc_no_condoms[$npclastgenerated] = rand(-2,2)
+		if npc_risktaker[$npclastgenerated] = 1:
+			npc_no_condoms[$npclastgenerated] = rand(-1,2)
+		else
+			npc_no_condoms[$npclastgenerated] = rand(-2,2)
+		end
 	end
+
+!! Preferred sexual position
+	npc_fav_pos[$npclastgenerated] = rand(1,7)
 	
-	!! if npc_caretaker = 1: they will frequently show love through acts of service
-	!! example: making you breakfast in bed
-	if npc_selfish[$npclastgenerated] ! 1: npc_caretaker[$npclastgenerated] = rand(-3,1)
+	if npc_fav_pos[$npclastgenerated] = 1:
+		$npc_fav_pos[$npclastgenerated] = 'miss'
+	elseif npc_fav_pos[$npclastgenerated] = 2:
+		$npc_fav_pos[$npclastgenerated] = 'doggy'
+	elseif npc_fav_pos[$npclastgenerated] = 3:
+		$npc_fav_pos[$npclastgenerated] = 'cowgirl'
+	elseif npc_fav_pos[$npclastgenerated] = 4:
+		$npc_fav_pos[$npclastgenerated] = 'blowjob'
+	elseif npc_fav_pos[$npclastgenerated] = 5:
+		$npc_fav_pos[$npclastgenerated] = 'titjob'
+	elseif npc_fav_pos[$npclastgenerated] = 6:
+		$npc_fav_pos[$npclastgenerated] = '69'
+	elseif npc_fav_pos[$npclastgenerated] = 7:
+		$npc_fav_pos[$npclastgenerated] = 'anal'
+	end
 	
-	!! npc_childfree determines that they never want to have kids and will react poorly to pregnancy related topics
-	npc_childfree[$npclastgenerated] = rand(-3,1)
+	!! npc_sex_speed determines whether they like it slow, steady, or fast and will cause them to select that speed more frequently
+	!! 1 is slow, 2 is steady, 3 is fast/rough
+	npc_sex_speed[$npclastgenerated] = rand(1,3)
+	if npc_sex_speed[$npclastgenerated] = 1 and rand(1,3) = 1:
+		!! npc has a tendency to be overly gentle and cautious
+		npc_gentle_lover[$npclastgenerated] = 1
+	elseif rand(1,3) = 1:
+		!! npc prefers sex with dirty talk and perverted acts
+		!! example: using spit instead of lube
+		npc_dirty_lover[$npclastgenerated] = 1
+	elseif rand(1,3) = 1:
+		!! npc prefers romantic and sensual sex
+		npc_sensual_lover[$npclastgenerated] = 1
+	end
+
+!! Preferred cumming location
+!!	0 = no preference
+	npc_cum_pref[$npclastgenerated] = rand(0,5)
 	
-	!! if npc_abusive = 1: the npc will be abusive
-	npc_abusive[$npclastgenerated] = rand(-3,1)
+	if npc_cum_pref[$npclastgenerated] = 1:
+		$npc_cum_pref[$npclastgenerated] = 'creampie'
+	elseif npc_cum_pref[$npclastgenerated] = 2:
+		$npc_cum_pref[$npclastgenerated] = 'mouth'
+	elseif npc_cum_pref[$npclastgenerated] = 3:
+		$npc_cum_pref[$npclastgenerated] = 'facial'
+	elseif npc_cum_pref[$npclastgenerated] = 4:
+		$npc_cum_pref[$npclastgenerated] = 'tits'
+	elseif npc_cum_pref[$npclastgenerated] = 5:
+		$npc_cum_pref[$npclastgenerated] = 'pullout'
+	end
+	
+	if rand(-3,1) = 1: npc_bukakke_fetish[$npclastgenerated] = 1
+	
+	
+!!	npc_tit_pref determines an npcs preference for breast size
+!!	if npc_tit_pref = 0: they don''t care
+!!	if npc_tit_pref = 1: they like small tits (A or smaller)
+!!	if npc_tit_pref = 2: they like medium sized tits (B to C)
+!!	if npc_tit_pref = 3: they like busty girls (D to E)
+!!	if npc_tit_pref = 4: they like oversized breasts (F+)
+	npc_tit_pref[$npclastgenerated] = rand(0,4)
 	
+!!	npc_bush_pref determines an npcs preference for the player''s shaving habits
+!!	if npc_bush_pref = 0: they don''t care
+!!	if npc_bush_pref = 1: they prefer it cleanshaven
+!!	if npc_bush_pref = 2: they like it trimmed or cleanshaven
+!!	if npc_bush_pref = 3: they like it bushy
+	npc_bush_pref[$npclastgenerated] = rand(0,3)
+	
+!! $npc_fav_body_part
+	if rand(1,4) = 1:
+		$npc_fav_body_part[$npclastgenerated] = 'pussy'
+	elseif rand(1,3) = 1:
+		$npc_fav_body_part[$npclastgenerated] = 'tits'
+	elseif rand(1,2) = 2:
+		$npc_fav_body_part[$npclastgenerated] = 'ass'
+	else
+		$npc_fav_body_part[$npclastgenerated] = 'thighs'
+	end
+	
+
 	!! if npc_sexdrive determines how likely the npc will be to engage in sexual behavior and how many times they can orgasm in a single sexual encounter
-	npc_sexdrive[$npclastgenerated] = rand(1,10)
+	if rand(1,10) <= 4:
+		npc_sexdrive[$npclastgenerated] = rand(3,5)
+	elseif rand(1,10) <= 3:
+		npc_sexdrive[$npclastgenerated] = rand(1,3)
+!!	elseif rand(1,10) <= 3:
+!!		npc_sexdrive[$npclastgenerated] = rand(1,10)
+!!	elseif rand(1,10) <= 2:
+!!		npc_sexdrive[$npclastgenerated] = rand(7,10)
+	else
+		!!failsafe
+		npc_sexdrive[$npclastgenerated] = rand(1,10)
+	end
+	
+	!! if npc_sex_stamina determines how long they can last in bed without cumming
+	
+	if rand(1,10) <= 4:
+		npc_sex_stamina[$npclastgenerated] = rand(3,5)
+	elseif rand(1,10) <= 3:
+		npc_sex_stamina[$npclastgenerated] = rand(1,3)
+!!	elseif rand(1,10) <= 3:
+!!		npc_sex_stamina[$npclastgenerated] = rand(1,10)
+!!	elseif rand(1,10) <= 2:
+!!		npc_sex_stamina[$npclastgenerated] = rand(7,10)
+	else
+		!!failsafe
+		npc_sex_stamina[$npclastgenerated] = rand(1,10)
+	end
+
+	!! npc_spanker determines whether or not they''re into spanking during sex
+	npc_sex_spanker[$npclastgenerated] = rand(-1,1)
+	
+	!! npc_childfree determines that they never want to have kids and will react poorly to pregnancy related topics
+	npc_childfree[$npclastgenerated] = rand(-3,1)
 	
 	!! if npc_pussyeater = 1: they have a fetish for eating pussy
-	npc_pussyeater[$npclastgenerated] = rand(-2,1)
+	!! if npc_pussyeater = -1: they refuse to eat pussy
+	npc_pussyeater[$npclastgenerated] = rand(-1,1)
 	
 	!! if npc_cuddler = 1: the npc likes to cuddle
 	npc_cuddler[$npclastgenerated] = rand(-1,1)
@@ -660,6 +814,73 @@ $npc_dna[$npclastgenerated] = func('DNA','create')
 	
 	!! if npc_two_pump = 1: the npc will always cum immediately in the first penetration act of sex
 	npc_two_pump[$npclastgenerated] = rand(-5,1)
+	
+!! ------------------------- date preferences ----------------------------------
+	!! favorite kind of date
+	if $npc_door_pref[$npclastgenerated] = 'indoor' and rand(1,3) < 3:
+		if rand(1,5) = 1:
+			$npc_fav_date[$npclastgenerated] = 'takeout_date'
+		elseif rand(1,4) = 1:
+			$npc_fav_date[$npclastgenerated] = 'coffee_date'
+		elseif rand(1,3) = 1:
+			$npc_fav_date[$npclastgenerated] = 'casual_meal'
+		elseif rand(1,2) = 1:
+			$npc_fav_date[$npclastgenerated] = 'netflix_chill'
+		elseif rand(1,1) = 1:
+			$npc_fav_date[$npclastgenerated] = 'movie_date'
+		end
+	elseif $npc_door_pref[$npclastgenerated] = 'outdoor' and rand(1,3) < 3:
+		if rand(1,6) = 1:
+			$npc_fav_date[$npclastgenerated] = 'picnic_date'
+		elseif rand(1,5) = 1:
+			$npc_fav_date[$npclastgenerated] = 'beach_date'
+		elseif rand(1,4) = 1:
+			$npc_fav_date[$npclastgenerated] = 'casual_meal'
+		elseif rand(1,3) = 1:
+			$npc_fav_date[$npclastgenerated] = 'fancy_meal'
+		elseif rand(1,2) = 1:
+			$npc_fav_date[$npclastgenerated] = 'amusement_park'
+		elseif rand(1,1) = 1:
+			$npc_fav_date[$npclastgenerated] = 'shopping_date'
+		end
+	else
+		if rand(1,4) = 1:
+			$npc_fav_date[$npclastgenerated] = 'picnic_date'
+		elseif rand(1,4) = 1:
+			$npc_fav_date[$npclastgenerated] = 'beach_date'
+		elseif rand(1,3) = 1:
+			$npc_fav_date[$npclastgenerated] = 'shopping_date'
+		elseif rand(1,2) = 1:
+			$npc_fav_date[$npclastgenerated] = 'fancy_meal'
+		elseif rand(1,1) = 1:
+			$npc_fav_date[$npclastgenerated] = 'amusement_park'
+		elseif rand(1,4) = 1:
+			$npc_fav_date[$npclastgenerated] = 'takeout_date'
+		elseif rand(1,3) = 1:
+			$npc_fav_date[$npclastgenerated] = 'casual_meal'
+		elseif rand(1,2) = 1:
+			$npc_fav_date[$npclastgenerated] = 'netflix_chill'
+		elseif rand(1,1) = 1:
+			$npc_fav_date[$npclastgenerated] = 'movie_date'
+		end
+	end
+	
+	!! npc_fav_genre determines what kind of media they like to consume
+	if rand(1,10) > 7:
+		$npc_fav_genre[$npclastgenerated] = 'action'
+	elseif rand(1,7) > 4:
+		$npc_fav_genre[$npclastgenerated] = 'horror'
+	elseif rand(1,5) > 2:
+		if rand(1,10) < npc_sexdrive[$npclastgenerated]:
+			$npc_fav_genre[$npclastgenerated] = 'raunchy_comedy'
+		else
+			$npc_fav_genre[$npclastgenerated] = 'comedy'
+		end
+	elseif rand(1,2) = 1:
+		$npc_fav_genre[$npclastgenerated] = 'drama'
+	else
+		$npc_fav_genre[$npclastgenerated] = 'romance'
+	end
 
 !! Variable clean up
 killvar '$npctempgn'

+ 5 - 0
locations/npcpreservec.qsrc

@@ -33,6 +33,7 @@ if mid($npctemp,1,1) = 'C':
 	$npc_notes[$npclastsaved]		= $npc_notes[$npctemp]
 	$npc_pic[$npclastsaved]			= $npc_pic[$npctemp]
 	
+	npc_age[$npclastsaved]			= npc_age[$npctemp]
 	npc_dob[$npclastsaved]			= npc_dob[$npctemp]
 	npc_gender[$npclastsaved]		= npc_gender[$npctemp]
 
@@ -91,9 +92,11 @@ if mid($npctemp,1,1) = 'C':
 	npc_intel[$npclastsaved]		= npc_intel[$npctemp]
 	npc_humor[$npclastsaved]		= npc_humor[$npctemp]
 	npc_fav_pos[$npclastsaved]		= npc_fav_pos[$npctemp]
+	$npc_fav_pos[$npclastsaved]		= $npc_fav_pos[$npctemp]
 	npc_sex_speed[$npclastsaved]	= npc_sex_speed[$npctemp]
 	npc_cum_pref[$npclastsaved]		= npc_cum_pref[$npctemp]
 	$npc_cum_pref[$npclastsaved]	= $npc_cum_pref[$npctemp]
+	$npc_bukakke_fetish[$npclastsaved]	= $npc_bukakke_fetish[$npctemp]
 	npc_tit_pref[$npclastsaved]		= npc_tit_pref[$npctemp]
 	npc_bush_pref[$npclastsaved]	= npc_bush_pref[$npctemp]
 
@@ -128,6 +131,8 @@ if mid($npctemp,1,1) = 'C':
 	npc_childfree[$npclastsaved]		= npc_childfree[$npctemp]
 	npc_abusive[$npclastsaved] 			= npc_abusive[$npctemp]
 	npc_sexdrive[$npclastsaved] 		= npc_sexdrive[$npctemp]
+	npc_sex_stamina[$npclastsaved] 		= npc_sex_stamina[$npctemp]
+	npc_sex_spanker[$npclastsaved] 		= npc_sex_spanker[$npctemp]
 	npc_pussyeater[$npclastsaved]		= npc_pussyeater[$npctemp]
 	npc_cuddler[$npclastsaved] 			= npc_cuddler[$npctemp]
 	npc_cum_cannon[$npclastsaved]		= npc_cum_cannon[$npctemp]

+ 1 - 1
locations/sex_ev_after.qsrc

@@ -1883,7 +1883,7 @@ if $ARGS[0] = 'spend_night_ask':
 				end
 			end
 			
-			if pcs_lovers - pcs_girlfriends > 0 and living_with_npc > 0:
+			if pcs_lover - pcs_girlfriends > 0 and living_with_npc > 0:
 				act'I don''t want to see my boyfriend(annoyed)':
 					cla & *clr
 					$sex_ev['bed_room']

+ 2 - 2
locations/sex_ev_condoms.qsrc

@@ -1037,7 +1037,7 @@ if $ARGS[0] = 'reenable_condoms1':
 			'"Huh? How come?"'
 			gs 'sex_ev_condoms', 'reenable_condoms1_stop_bc'
 			
-			if pcs_lovers - pcs_girlfriends > 0 and $sex_ev['type'] ! 'married_sex' and $sex_ev['type'] ! 'dating_sex':
+			if pcs_lover - pcs_girlfriends > 0 and $sex_ev['type'] ! 'married_sex' and $sex_ev['type'] ! 'dating_sex':
 				act'Trying for baby':
 					gs 'sex_ev_condoms', 'trying_for_baby'
 					gs 'sex_ev_condoms', 'reenable_condoms2'
@@ -1824,7 +1824,7 @@ if $ARGS[0] = 'no_more_free_creampies3':
 		end
 	end
 	
-	if pcs_lovers - pcs_girlfriends > 0:
+	if pcs_lover - pcs_girlfriends > 0:
 		act'Trying for baby with lover':
 			gs 'sex_ev_condoms', 'trying_for_baby'
 			gs 'sex_ev_condoms', 'no_more_free_creampies4'

+ 2 - 2
locations/sex_ev_cum.qsrc

@@ -584,9 +584,9 @@ if $ARGS[0] = 'fuck_cum':
 !!		*nl
 !!		'Tell hornguy6 that the fuck_cum failsafe activated.'
 !!		act'Continue':gt 'sex_ev_cum', 'cum_pullout'
+	elseif sex_ev['boy_cum'] < 1:
+		gs'sex_ev_cum', 'girl_cum'
 	end
-	
-	gs'sex_ev_cum', 'girl_cum'
 end
 
 if $ARGS[0] = 'cum_his_choice':

+ 1 - 1
locations/sex_ev_hookup_leave.qsrc

@@ -358,7 +358,7 @@ if $ARGS[0] = 'just_a_hookup':
 end
 
 if $ARGS[0] = 'have_a_boyfriend':
-	if pcs_lovers - pcs_girlfriends > 0:
+	if pcs_lover - pcs_girlfriends > 0:
 		act'I have a boyfriend':
 			npc_know_girlfriend[$boy] = 0
 			cla & *clr

+ 2 - 2
locations/sex_ev_leave.qsrc

@@ -489,7 +489,7 @@ if $ARGS[0] = 'unsatisfied_breakup':
 end
 
 if $ARGS[0] = 'no_more_cheating_breakup':
-	if pcs_lovers > 0 and (npc_know_have_boyfriend + npc_know_have_girlfriend = 0):
+	if pcs_lover > 0 and (npc_know_have_boyfriend + npc_know_have_girlfriend = 0):
 		act'I''ve started seeing somebody':
 			cla & *clr
 			npc_know_cheat[$boy] = 1
@@ -544,7 +544,7 @@ if $ARGS[0] = 'no_more_cheating_breakup':
 			end
 		end
 		
-		if pcs_lovers - pcs_girlfriends > 0:
+		if pcs_lover - pcs_girlfriends > 0:
 			act'I can''t keep cheating on my boyfriend':
 				cla & *clr
 				'<center><video autoplay loop src="images/shared/romance/misc/depart_annoyed1.mp4"></video></center>'

+ 27 - 26
locations/sex_ev_miss.qsrc

@@ -158,7 +158,7 @@ if $ARGS[0] = 'miss1':
 	gs 'sex_ev_sex', 'fuck_arousal_code'
 	if mesec > 0:
 		if sex_ev['condom'] = 1:
-			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom_discard1.jpg"></center>'
+			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom1.jpg"></center>'
 		else
 			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood1.jpg"></center>'
 		end
@@ -369,7 +369,7 @@ if $ARGS[0] = 'miss2':
 	gs 'sex_ev_sex', 'fuck_arousal_code'
 	if mesec > 0:
 		if sex_ev['condom'] = 1:
-			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom_discard1.jpg"></center>'
+			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom1.jpg"></center>'
 		else
 			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood1.jpg"></center>'
 		end
@@ -571,14 +571,15 @@ if $ARGS[0] = 'miss3':
 	if pcs_vag = 0 and sex_ev['fuck_count'] = 0:gt 'sex_ev_virgin', 'miss_virg_hard1'
 	gs 'arousal', 'vaginal',1,'no_orgasm_msg', 'rough'
 	'<center><video autoplay loop src="images/shared/sex/vag/miss/rough1.mp4"></video></center>'
-	'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his cock.'
+	gs 'sex_ev_miss', 'miss3_start_desc'
 	*nl
 	if mesec > 0:
 		gs 'sex_ev_miss', 'miss3_start_period_desc'
 	else
-		
-		gs 'sex_ev_miss', 'miss3_start_desc'
+		*nl
+		'He pummels your pussy with tremendous strength, sending the sound of your clapping cheeks echoing off the walls and driving the breath from your lungs.'
 	end
+	
 	act'Enjoy it':
 		pcs_sweat += 1
 		sex_ev['orgasm'] = orgasm
@@ -1534,27 +1535,27 @@ end
 if $ARGS[0] = 'miss3_start_period_desc':
 !!	'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous force and the sound of your cheeks getting clapped echoes off the walls. His cock slams into you and you can feel it force the menstrual blood from your uterus, sending it running down your thighs.'
 	if $npc_dick_desc[$boy] = 'tiny' or $npc_dick_desc[$boy] = 'short':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His tiny dick slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His tiny dick slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'chode':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His tiny dick slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His tiny dick slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'skinny':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His skinny dick slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His skinny dick slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'normal':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His dick slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His dick slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'thick':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His thick cock slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His thick cock slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'long':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His long cock slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His long cock slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'huge':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His huge cock slams into you with such power that the menstrual blood is forced from your uterus and sent running down your ass.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His huge cock slams into you with such power that you can feel your period spattering across the inside of your thighs.'
 	elseif $npc_dick_desc[$boy] = 'enormous':
 		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His enormous cock slams into you with such power that your pussy is left no room for the blood leaking from your uterus and flecks of red spatter across the sheets.'
 	elseif $npc_dick_desc[$boy] = 'lengthy':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His lengthy cock is so long that it slams into your cervix, battering the blood from your uterus and sending flecks of red spatter across the sheets.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His cock is so long that it slams into your cervix, battering the blood from your uterus and sending flecks of red spatter across the sheets.'
 	elseif $npc_dick_desc[$boy] = 'gigantic':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His gigantic cock is so long that it slams into your cervix, filling you completely and battering the blood from your uterus, flecks of red sent spattering across the sheets.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His gigantic cock is so huge that it slams into your cervix, filling you completely and battering the blood from your uterus, flecks of red sent spattering across the sheets.'
 	elseif $npc_dick_desc[$boy] = 'monster':
-		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His monstrous cock is so long that it slams into your cervix, while also being so girthy that it feels like the blood could be coming from your pussy getting torn in half, rather than your period.'
+		'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous strength and the sound of your cheeks getting clapped echoes off the walls. His monstrous cock is so huge that it slams into your cervix, while also being so girthy that it feels like the blood could be coming from your pussy getting torn in half, rather than your period.'
 	end
 end
 
@@ -1562,27 +1563,27 @@ end
 if $ARGS[0] = 'miss3_start_desc':
 !!	'<<$npc_firstname[$boy]>> drives himself in and out of your pussy with tremendous force and the sound of your cheeks getting clapped echoes off the walls.'
 	if $npc_dick_desc[$boy] = 'tiny' or $npc_dick_desc[$boy] = 'short':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust, but not so hard that he''s jackhammering you. Wet slaps echo around the room as his hips collide with yours, unceasingly thrusting into you with his tiny dick.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his hips into you. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his tiny dick. You can barely feel him inside you, but the impact of his body leaves you breathless.'
 	elseif $npc_dick_desc[$boy] = 'chode':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust, but not so hard that he''s jackhammering you. Wet slaps echo around the room as his hips collide with yours, unceasingly thrusting into you with his thick chode.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his hips into you, impact rippling through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his fat chode.'
 	elseif $npc_dick_desc[$boy] = 'skinny':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust, but not so hard that he''s jackhammering you. Wet slaps echo around the room as his hips collide with yours, unceasingly thrusting into you with his skinny dick.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his skinny dick.'
 	elseif $npc_dick_desc[$boy] = 'normal':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust, but not so hard that he''s jackhammering you. Wet slaps echo around the room with every thrust and he drives his cock deep as deep as he can every time.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his cock.'
 	elseif $npc_dick_desc[$boy] = 'thick':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust, but not so hard that he''s jackhammering you. Wet slaps echo around the room as his hips collide with yours, the sloppy squelching sounds of your pussy fucked by his thick shaft.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his thick shaft.'
 	elseif $npc_dick_desc[$boy] = 'long':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust and his long dick hammers deep inside you. Wet slaps echo around the room as his hips collide with yours, the sloppy sounds of your pussy squelching around his long shaft.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to pull you harder onto his long shaft.'
 	elseif $npc_dick_desc[$boy] = 'huge':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust and his dick hammers deep inside you. Wet slaps echo around the room as his hips collide with yours, the huge size of his cock forcing squelches from your cunt.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to force his huge cock deeper inside you.'
 	elseif $npc_dick_desc[$boy] = 'enormous':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust and his enormous dick fills you to the brim. Wet slaps echo around the room as his hips collide with yours, forcing loud squelches from your snatch with his long girthy cock.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to force his enormous cock deeper inside you.'
 	elseif $npc_dick_desc[$boy] = 'lengthy':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust and his dick batters your insides with its exceptional length. Wet slaps echo around the room as his hips collide with yours, the sloppy sounds of your pussy squelching around his lengthy shaft.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to force his lengthy shaft as deep as it can go inside you.'
 	elseif $npc_dick_desc[$boy] = 'gigantic':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust and his gigantic dick fills you to the brim. Sloppy wet slaps echo around the room as <<$npc_firstname[$boy]>> batters your pussy with his long hard cock.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to force as much of his gigantic cock inside you as he can.'
 	elseif $npc_dick_desc[$boy] = 'monster':
-		'<<$npc_firstname[$boy]>> drives into you at a steady pace, hard enough that your breasts jiggle with every thrust. His dick fills you completely and then some, forcing your pussy to strain and stretch around his long, girthy shaft. Sloppy wet slaps echo around the room as <<$npc_firstname[$boy]>> repeatedly batters your pussy with his monstrous cock.'
+		'You gasp as <<$npc_firstname[$boy]>> slams his cock into you and the impact ripples through your entire body. As your head jerks forward, <<$npc_firstname[$boy]>>''s hand grabs hold of your hair, yanking on it to force as much of his monstrously huge cock inside you as he can.'
 	end
 end
 

+ 6 - 2
locations/sex_ev_morning.qsrc

@@ -45,8 +45,12 @@ if $ARGS[0] = 'morning':
 		gs'sex_ev_morning', 'after_sleepfuck_wake'
 		
 		if $boy ! one_of_svetas_lovers:
-			if pcs_lovers - pcs_girlfriends > 0:act'Your boyfriend':$sex_ev['cheat'] = 'boyfriend' & gt'sex_ev_morning', 'guilt1'
-			if pcs_girlfriends > 0:act'Your girlfriend': $sex_ev['cheat'] = 'girlfriend' & gt'sex_ev_morning', 'guilt1'
+			if pcs_lover - pcs_girlfriends > 0:
+				act'Your boyfriend':$sex_ev['cheat'] = 'boyfriend' & gt'sex_ev_morning', 'guilt1'
+			end
+			if pcs_girlfriends > 0:
+				act'Your girlfriend': $sex_ev['cheat'] = 'girlfriend' & gt'sex_ev_morning', 'guilt1'
+			end
 		end
 		
 		if pilldaychk < daystart - 1 and birth_control['using_bc'] = 1: gs'sex_ev_morning', 'forgot_bc_pill'

+ 3 - 3
locations/sex_ev_pillow_talk.qsrc

@@ -214,7 +214,7 @@ if $ARGS[0] = 'sorry_didnt_cum':
 end
 
 if $ARGS[0] = 'better_than_boyfriend':
-	if pcs_lovers - pcs_girlfriends > 0 and sex_ev['better_than_lover_talk'] = 0 and sex_ev['virgin'] = 0:
+	if pcs_lover - pcs_girlfriends > 0 and sex_ev['better_than_lover_talk'] = 0 and sex_ev['virgin'] = 0:
 		act'You''re better than my boyfriend':
 			sex_ev['better_than_lover_talk'] = 1
 			npc_know_have_boyfriend[$boy] = 1
@@ -269,7 +269,7 @@ if $ARGS[0] = 'sore_pussy':
 							gs'sex_ev_pillow_talk', 'sex_talk'
 						end
 						
-						if npc_rel_type[$boy] ! 'boyfriend' and pcs_lovers - pcs_girlfriends > 0:
+						if npc_rel_type[$boy] ! 'boyfriend' and pcs_lover - pcs_girlfriends > 0:
 							act'Wish my boyfriend was that big':
 								npc_know_cheat[$boy] = 1
 								cla & *nl
@@ -2470,7 +2470,7 @@ if $ARGS[0] = 'pubes_other_lovers':
 			gs'sex_ev_pillow_talk', 'boy_pubes_response'
 		end
 		
-		if pcs_lovers > 0 and pcs_lovers - pcs_girlfriends > 0:
+		if pcs_lover > 0 and pcs_lover - pcs_girlfriends > 0:
 			act'My boyfriend likes it':
 				cla & *nl
 				'"My boyfriend likes it this way," you shrug. "Why do you ask?"'

+ 1 - 1
locations/sex_ev_pillow_talk2.qsrc

@@ -1461,7 +1461,7 @@ if $ARGS[0] = 'share_life_menu':
 end
 
 if $ARGS[0] = 'share_life_single':
-	if pcs_lovers + pcs_girlfriends = 0:
+	if pcs_lover + pcs_girlfriends = 0:
 		act'Single now':
 			
 			cla

+ 3 - 3
locations/sex_ev_reactions.qsrc

@@ -906,7 +906,7 @@ if $ARGS[0] = 'thought_no_creampies':
 			if npc_abusive[$boy] = 1 or npc_selfish[$boy] = 1:
 !!				if rand(0,1) = 1:
 					'"Finally break up with your shitty boyfriend?" <<$npc_firstname[$boy]>> grins, panting.'
-					if pcs_lovers = 0:
+					if pcs_lover = 0:
 						act'Yeah':
 							npc_boyfriend_creampie_rule[$boy] = 0
 							cla & *nl
@@ -958,7 +958,7 @@ if $ARGS[0] = 'thought_no_creampies':
 					end
 !!{				else
 					'"Finally decided to let a real man fill you up, huh?" <<$npc_firstname[$boy]>> grins, panting.'
-					if pcs_lovers = 0:
+					if pcs_lover = 0:
 						act'I''m single now':
 							npc_boyfriend_creampie_rule[$boy] = 0
 							cla & *nl
@@ -970,7 +970,7 @@ if $ARGS[0] = 'thought_no_creampies':
 				end}
 			else
 				'"I thought," <<$npc_firstname[$boy]>> pants. "You said I wasn''t allowed to come inside you? Something about your boyfriend?"'
-				if pcs_lovers = 0:
+				if pcs_lover = 0:
 					act'I''m single now':
 						npc_boyfriend_creampie_rule[$boy] = 0
 						cla & *nl

+ 1 - 1
locations/sex_ev_sex.qsrc

@@ -1418,7 +1418,7 @@ if $ARGS[0] = 'sleep_sex':
 		*nl
 		if $sex_ev['type'] = 'married_sex' or husband > 0:
 			'It''s a <i>good</i> dream. You''re rocking back and forth on a your husband''s cock, riding him like there''s no tomorrow as it fills your pussy in all the right ways.'
-		elseif $npc_rel_type[$boy] = 'boyfriend' or pcs_lovers - pcs_girlfriends > 0:
+		elseif $npc_rel_type[$boy] = 'boyfriend' or pcs_lover - pcs_girlfriends > 0:
 			'It''s a <i>good</i> dream. You''re rocking back and forth on a your boyfriend''s cock, riding him like there''s no tomorrow as it fills your pussy in all the right ways.'
 		elseif pcs_girlfriends > 0:
 			'It''s a <i>good</i> dream. You''re rocking back and forth on a your girlfriend''s strapon, riding her like there''s no tomorrow as it fills your pussy in all the right ways.'

+ 3 - 3
locations/sex_ev_shower.qsrc

@@ -464,7 +464,7 @@ if $ARGS[0] = 'before_shower_creampie':
 				end
 			end
 			
-			if pcs_lovers - pcs_girlfriends = 0 and npc_boyfriend_creampie_rule[$boy] > 0:
+			if pcs_lover - pcs_girlfriends = 0 and npc_boyfriend_creampie_rule[$boy] > 0:
 				act'Rule no longer applies':
 					if npc_boyfriend_creampie_rule[$boy] > 0: npc_boyfriend_creampie_rule[$boy] = 0
 					cla & *clr
@@ -1015,7 +1015,7 @@ if $ARGS[0] = 'after_shower_creampie':
 					gs'sex_ev_shower', 'after_shower_clean_options'
 				end
 			end
-			if pcs_lovers - pcs_girlfriends = 0:
+			if pcs_lover - pcs_girlfriends = 0:
 				act'Changed my mind':
 					if npc_boyfriend_creampie_rule[$boy] > 0: npc_boyfriend_creampie_rule[$boy] = 0
 					cla & *clr
@@ -1703,7 +1703,7 @@ if $ARGS[0] = 'morning_shower_creampie':
 				end
 			end
 			
-			if pcs_lovers - pcs_girlfriends = 0:
+			if pcs_lover - pcs_girlfriends = 0:
 				act'Changed my mind':
 					if npc_boyfriend_creampie_rule[$boy] > 0: npc_boyfriend_creampie_rule[$boy] = 0
 					cla & *clr

+ 1 - 0
locations/sex_ev_stats.qsrc

@@ -3,6 +3,7 @@
 if $ARGS[0] = 'npc_update':
 	gs 'boy_updater', 'fav_body_part'
 	gs 'boy_updater', 'dick_update'
+	gs 'boy_updater', 'stamina_update'
 end
 
 if $ARGS[0] = 'starting_stats':

+ 3 - 3
locations/sex_ev_virgin.qsrc

@@ -668,7 +668,7 @@ if $ARGS[0] = 'miss_virg_norm1.1':
 	act'Continue':
 		cla & *clr
 		if sex_ev['condom'] = 1:
-			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom_discard1.jpg"></center>'
+			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom1.jpg"></center>'
 		else
 			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood1.jpg"></center>'
 		end
@@ -723,7 +723,7 @@ if $ARGS[0] = 'miss_virg_hard1':
 	$sex_ev['position'] = 'miss'
 	$sex_ev['pos_speed'] = 'miss3'
 	if sex_ev['condom'] = 1:
-		'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom_discard1.jpg"></center>'
+		'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood_condom1.jpg"></center>'
 	else
 		'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/blood1.jpg"></center>'
 	end
@@ -1981,7 +1981,7 @@ if $ARGS[0] = 'kiss_turn_head':
 			gs'sex_ev_pillow_talk', 'topic_route'
 		end
 		
-		if pcs_lovers > 0:
+		if pcs_lover > 0:
 			act'I have a boyfriend':
 				cla & *nl
 				'"Don''t do that," you say, not meeting his eyes. "I have a boyfriend."'

+ 12 - 1
locations/wardrobe.qsrc

@@ -511,7 +511,12 @@ if $ARGS[0] = 'default_entry_wear':
 	end
 
 	if defunderwear[default_entry] = 2:
-		if dyneval('RESULT = <<$defbodysuittype[default_entry]>>_bodysuits[<<defbodysuitnumber[default_entry]>>]') = 0:
+		if hypnoPanty = 1 or hypnoBra = 1:
+			!! removal of underwear from set if therapist has prohibited it
+			$defbodysuittype[default_entry] = 'none' & defbodysuitnumber[default_entry] = 0
+			defunderwear[default_entry] = 0
+			msg '<center>You feel like something about this set has changed but you cannot workout what it is.</center>'
+		elseif dyneval('RESULT = <<$defbodysuittype[default_entry]>>_bodysuits[<<defbodysuitnumber[default_entry]>>]') = 0:
 			$defbodysuittype[default_entry] = 'none' & defbodysuitnumber[default_entry] = 0
 		end
 		if $defbodysuittype[default_entry] = 'none':
@@ -522,6 +527,12 @@ if $ARGS[0] = 'default_entry_wear':
 	end
 
 	if defunderwear[default_entry] = 0:
+		if (hypnoPanty = 1 and $pantyworntype ! 'none') or (hypnoBra = 1 and $braworntype ! 'none'):
+			!! removal of underwear from set if therapist has prohibited it
+			if hypnoPanty = 1 and $pantyworntype ! 'none': $defpantytype[default_entry] = 'none' & defpantynumber[default_entry] = 0
+			if hypnoBra = 1 and $braworntype ! 'none': $defbratype[default_entry] = 'none' & defbranumber[default_entry] = 0
+			msg '<center>You feel like something about this set has changed but you cannot workout what it is.</center>'
+		end
 		if dyneval('RESULT = <<$defpantytype[default_entry]>>_panties[<<defpantynumber[default_entry]>>]') = 0:
 			$defpantytype[default_entry] = 'none' & defpantynumber[default_entry] = 0
 		end

+ 158 - 0
tools/callvalidator-readme.md

@@ -0,0 +1,158 @@
+
+## Call Validator Readme
+
+The `callvalidator.py` is a simple python script that tries to find out whether a call (`gt 'location', :p`) is valid or not.
+
+A call is valid if the `location` exists and there is at least one `if $ARGS[0] = :p` or `if ARGS[0] = :p` or similar code present in the `location`’s code. In other words, the call won’t result in a `“Location doesn’t exist”` error.
+
+As QSP doesn’t provide a standard way to handle these calls - `$ARGS[0]` can used simple as `$value = $ARGS[0]` - there is no way to make this 100% correct.  
+Nonetheless I tried to cover as many scenarios as I could.
+
+Even with this currently two files are skipped: `boyStat.qsrc` and `exp_gain.qsrc` as there is no easy to decide whether a value passed in `$ARGS[0]` or `ARGS[0]` is valid or not.
+
+### Running the script
+
+The script can be run with `python callvalidator.py soure=<folder> [file=<filename> | list=<listfilename>] [folder=<folder>]`
+
+1. Calling `python callvalidator.py source=locations` will run the validator on every `.qsrc` file in the `locations` folder.
+2. Calling `python callvalidator.py source=locations file=albina_wine_event.qsrc` will run the validator against the `albina_wine_event.qsrc` file and because no `folder=<folder>` parameter is specified it will assume that the file is in the folder specified by `source=locations`.
+3. Calling `python callvalidator.py source=locations file=albina_wine_event.qsrc folder=workfolder` will look for the `albina_wine_event.qsrc` file in the `workfolder` folder and will check the calls made in the file against the files in the `locations` folder.
+4. Calling `python callvalidator.py source=locations list=listoffiles.txt` will read the `listoffiles.txt` file and will validate every file that is listed. If the `folder` parameter is not passed, it will for `listoffiles.txt` in the folder defined by `source`, i.e. in the `locations` folder. If the `folder` parameter is passed, then the validator will look for `listoffiles.txt` in that folder.
+5. the `file=` and `list=` parameters can’t be used at the same time (at the moment).
+
+### File list files
+
+The files that can be passed in the `list=<listfilename>` have to conform to one of two forms:
+
+#### Simple text file
+
+The simplest is a simple text file  
+Just add the file names (one per line) and optionally the folder, separated by `;`
+
+```
+alexandriaEv.qsrc
+albina_wine_event.qsrc;locations
+```
+
+If the validator finds any lines that don’t match this expectation it will quit with an error.  
+The validator can’t check whether the filename or the folder name is valid and if it receives something like
+```
+albina_\I'm_funn.qsrc;loc:ations
+```
+It will simply blow up.  
+I will add some checks to avoid this, but right now it will just exit with an error.
+
+#### XML File
+
+The XML file is a bit more complicated, and know the same:
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<FileList>
+	<Structure>
+		<File name="alexandriaEv.qsrc" folder="locations"/>
+		<File name="albina_wine_event.qsrc" folder="locations"/>
+		<File name="alex.qsrc" folder="locations"/>
+		<File name="dimaEv.qsrc" folder="locations"/>
+	</Structure>
+</FileList>
+```
+
+Every file goes into a `<File>` tag with two attributes: `name` and `folder`.  
+In the XML file both are mandatory, so the `folder` must be specified unlike in the text file.
+
+### Interpreting the output
+
+```jsx
+----- Summary -----
+  Locations called incorrectly    : 010 // The number of invalid 'location', :p pairs that don't exist
+  Non-existing locations called   : 002 // The location called doesn't exists
+  Number of incorrect calls       : 019 // The total number of incorrect calls made to invalid 
+                                        // 'location', :p pairs 
+  Locations making incorrect calls: 003 // The number of locations calling invalid 'location', :p pairs  
+  Locations never called          : 000 // Only shows up when the whole locations folder is checked,
+                                        // the number of locations that do exist, but no one calls them. 
+
+----- Validated files ----- 
+//the list of files that were validated. 
+//Only shown when the validator is run with a validation list file as the input.
+  locations\alexandriaEv.qsrc
+  locations\albina_wine_event.qsrc
+  locations\alex.qsrc
+  locations\dimaEv.qsrc
+  locations\uni_dorm.qsrc
+  locations\volleyball.qsrc
+
+----- List of Invalid calls -----  
+// a list of all the invalid 'location', :p pairs that were called.
+// the structure is: 'location', :p  : the reason the pair is invalid.
+
+  'albina_dorm', 'start' : albina_dorm.qsrc doesn't exist.
+
+  'albina_wine_event', 'shave_answer3' : No $ARGS[0] or ARGS[i] expecting 'shave_answer3'
+
+  'defeat', ''	: defeat.qsrc doesn't exist.
+
+  'victory', ''	: victory.qsrc doesn't exist.
+
+  'volleyball', 'collapse'	: No $ARGS[0] or ARGS[i] expecting 'collapse'
+  'volleyball', 'drive_back'	: No $ARGS[0] or ARGS[i] expecting 'drive_back'
+  'volleyball', 'fake_spike'	: No $ARGS[0] or ARGS[i] expecting 'fake_spike'
+  'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+  'volleyball', 'receive1'	: No $ARGS[0] or ARGS[i] expecting 'receive1'
+  'volleyball', 'recieve_practice'	: No $ARGS[0] or ARGS[i] expecting 'recieve_practice'
+
+
+----- List of Locations and invalid calls they make  
+
+// All the locations that made invalid calls, with a list of the calls they made.
+// The structure is
+// ---- location name [the file of the location]:  In case the same location name is used in more than one file
+//   line number, type of call 'location', :p : the reason the pair is invalid.
+
+  ---- albina_wine_event [locations\albina_wine_event.qsrc]:
+    invalid call on line 0176: gs 'albina_wine_event', 'shave_answer3'	: No $ARGS[0] or ARGS[i] expecting 'shave_answer3
+    
+  ---- uni_dorm [locations\uni_dorm.qsrc]:
+    invalid call on line 0222: gs 'albina_uni_schedule', ''	: albina_uni_schedule.qsrc doesn't exist.
+    invalid call on line 0236: gt 'albina_dorm', 'start'	: albina_dorm.qsrc doesn't exist.
+
+  ---- volleyball [locations\volleyball.qsrc]: 
+    invalid call on line 0136: gt 'volleyball', 'recieve_practice'	: No $ARGS[0] or ARGS[i] expecting 'recieve_practice'
+    invalid call on line 0230: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0250: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0260: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0264: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0270: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0310: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0334: gt 'volleyball', 'practice_end2'	: No $ARGS[0] or ARGS[i] expecting 'practice_end2'
+    invalid call on line 0372: gt 'volleyball', 'receive1'	: No $ARGS[0] or ARGS[i] expecting 'receive1'
+    invalid call on line 0430: gt 'victory', ''	: victory.qsrc doesn't exist.
+    invalid call on line 0432: gt 'defeat', ''	: defeat.qsrc doesn't exist.
+    invalid call on line 0434: gt 'volleyball', 'player_substitution'	: No $ARGS[0] or ARGS[i] expecting 'player_substitution'
+    invalid call on line 0436: gt 'volleyball', 'collapse'	: No $ARGS[0] or ARGS[i] expecting 'collapse'
+    invalid call on line 0481: gt 'volleyball', 'drive_back'	: No $ARGS[0] or ARGS[i] expecting 'drive_back'
+    invalid call on line 0494: gt 'volleyball', 'drive_back'	: No $ARGS[0] or ARGS[i] expecting 'drive_back'
+    invalid call on line 0642: gs 'volleyball', 'fake_spike'	: No $ARGS[0] or ARGS[i] expecting 'fake_spike'
+
+----- List of Locations that are never called -----
+//  A list of all the locations that do exist, but no call is made to them. 
+//  Only shows up when a whole folder is checked, not when a single file or a list of files is passed.
+  
+```
+
+### How does it work
+
+It is fairly rudimentary at the moment.  
+The validator loads the files that we want to validate (every file in the folder, the files defined in the list or the file that was passed as a parameter), and finds every `gs|gt|xgs|xgt 'location', :p` occurrence, and builds a list of files to check - `location.qsrc`.
+
+>One issue with this currently is that if there is a `location` where the related file is not `location.qsrc` but `somethingelse.qsrc` then it won’t be checked.
+
+In the next step it loads every file from the list.  
+If a file doesn’t exist then every call to that `location` will be marked `<location>.qsrc doesn't exist.`  
+If the file exists the validator checks if there are any lines containing `args[0]=:p`, `$if$args[0]=:p`, `args[i]=:p` or `$args[0]=:p` .  
+If a line is found, and the line starts with `if $args`, `if args`, `elseif args` or `elseif $args` it will mark the call as valid.  
+Lines starting with `!`, i.e. comment lines, are ignored, and lines that are placed `!{` and `}`, i.e. block comments, are ignored too.  
+Any call where the `location` exists, but no lines are found in the above step will be marked with `No $ARGS[0] or ARGS[i] expecting :p`
+
+Finally, the validator generates a report file, naming following the pattern of `call_validity [<folder>|<file>|<listfile>] - YYYYMMDDhhmmss`, for example: `call_validity [filesToValidate.txt] - 20230622135554.txt`

+ 236 - 68
tools/callvalidator.py

@@ -1,6 +1,6 @@
 #!/usr/bin/env python
-# usage: txtmerge.py <input_dir> <output_file_name> 
-# does the exact opposite of txtsplit.py
+# usage:callvalidator.py source=<src_input_dir> [file=<filename> | list=<listfilename>] [folder=<folder>]
+# tries to determine whether calls like gt 'location', 'event' are valid or not.
 
 from os import listdir
 from os.path import isfile, join
@@ -8,125 +8,293 @@ import sys
 import re
 import io
 import time
+import xml.etree.ElementTree as ET
 
+idir = ''
 callList = []
 locationCallList = []
+neverCalledLocations = []
+callFileList = []
+calledFileList = []
+validate = 'all'
+
+def loadValidationList(validationListFile):
+    result = []
+    try:
+        tree = ET.parse(validationListFile)
+        root = tree.getroot()
+        for file in root.iter('File'):
+            result.append(join(file.attrib['folder'], file.attrib['name']))
+            return result
+    except:
+        pass
+    #endtry
+
+    try: 
+        with io.open(validationListFile, 'r', encoding='utf-8') as ifile:
+            lines = ifile.readlines()
+            index = 1
+            for line in lines:
+                temp = line.strip(" \r\n\t").split(";")
+                file = temp[0].strip(" \t")
+                folder = idir
+                if ".qsrc" not in file:
+                    raise SyntaxError("Incorrect file content: '<filename>[; <folder>] expected, found %s." % (index, line),(validationListFile, index, 1, 'if ".qsrc" not in temp[0].strip(" \t"):', index, len(line)))
+                if len(temp) == 2:
+                    folder = temp[1].strip(" \t")
+                result.append(join(folder,file))
+                index += 1
+            return result
+    except SyntaxError as e:
+        raise SystemExit("Invalid list filed: %s" % e.msg)
+    #endtry
+#enddef
 
 
 def functionEmptyOrNamed(callArray):
-    if len(callArray) == 1:
-        return None
+    if len(callArray) < 3:
+        return ''
     else:
-        return callArray[1].strip(" \t\n").lower()
+        return callArray[2].strip(" \t\n")
     #endif
 #enddef
 
-def processLines(lines):
-    pattern = "(gt|gs|xgt|xgs)\s*('|\")\w+('|\")(,\s*('|\")\w+('|\"))?"
-    locationCalls = {"calllocation": lines[0].strip(' #\n').lower(), "callIds": []}
-        
+def processLines(lines, fileName):
+    findPattern = "(gt|gs|xgt|xgs)\s*('|\")\w+('|\")(,\s*('|\")\w+('|\"))?"
+    blockEndPattern = "[^}]*}$"
+    commentBlock = False
+    lineNo = 0
+    locationCalls = {"calllocation": lines[0].strip(' #\n'), "fileName": fileName, "calls": []}
     for line in lines:
-        if not line.strip(" \t").startswith("!"): 
-            match = re.search(pattern, line)
+        line = line.strip(" \t\n")  
+        if (not commentBlock) and line.strip("!").startswith("{"):
+            commentBlock = True
+        if commentBlock and (line == '}' or re.search(blockEndPattern, line) != None):
+            commentBlock = False
+        if not commentBlock and not line.startswith("!"): 
+            match = re.search(findPattern, line)
             if match != None:
-                temp = match.group().strip('xgst\t\n').replace('"','').replace("'", "").replace(" ","").split(",")
-                loc = temp[0].lower()
-                fun = functionEmptyOrNamed(temp)
-                call = {"location": loc, "function": fun, "valid": 0}
-                if call not in callList:
-                    callList.append(call)
-                    locationCalls['callIds'].append(len(callList)-1) 
-                elif callList.index(call) not in locationCalls['callIds']:
-                    locationCalls['callIds'].append(callList.index(call))
+                temp = match.group().replace('\t', '').replace(' ', '').replace("','","|").replace('","','|').strip(" '\n").replace("'","|").replace('"','|').split('|')
+                temp = [t.strip(" '\"") for t in temp]
+                if temp[1].lower() not in ['boystat', 'exp_gain']:
+                    calltype = temp[0]
+                    loc = temp[1]
+                    fun = functionEmptyOrNamed(temp)
+                    if ("%s.qsrc" % loc) not in calledFileList:
+                        calledFileList.append("%s.qsrc" % loc)
+                    calledLocation = {"location": loc, "function": fun, "valid": 0, "reason": "%s.qsrc doesn't exist." % loc}
+                    callLine = {"callId": 0, "calltype": calltype, "call": "%s '%s', '%s'" % (calltype, loc, fun), "lineNo": lineNo} 
+                    if calledLocation not in callList:
+                        callList.append(calledLocation)
+                    callLine['callId'] = callList.index(calledLocation)    
+                    locationCalls['calls'].append(callLine) 
                 #endif
             #endif
         #endif
+        lineNo += 1
     #endfor
 
     locationCallList.append(locationCalls)
 #enddedf 
 
 def validateCalls(lines):
-    calls = [c for c in callList if c['location'] == lines[0].strip(' #\n').lower()]
+    calls = [c for c in callList if c['location'].lower() == lines[0].strip(' #\n').lower()]
+    
+    if validate == 'all' and (calls == None or len(calls) == 0):
+        neverCalledLocations.append(lines[0].strip(' #\n').lower())
 
     for call in calls:
-        if call['function'] == None or call['function'] == 'start' or call['function'] == '':
+        if call['function'] == 'start' or call['function'] == 'Start' or call['function'] == '':
             call['valid'] = 1
+            call['reason'] = ""
         else:
-            findString = "if$args[0]='%s'" % call['function'].lower()
-            findString2 = "if$args[i]='%s'" % call['function'].lower()
-            targets = [line.replace(" ", "").lower().strip(' \n\t') for line in lines if findString in line.replace(" ", "").lower() or findString2 in line.replace(" ", "").lower()]
-            for t in targets:
-                if t.startswith("if$args[") or t.startswith("elseif$args["):
+            call['reason'] = "No $ARGS[0] or ARGS[i] expecting '%s'" % call['function']
+            findPattern = "\$*(args|ARGS)\[(0|i)\]\s*=\s*('|\")%s('|\")" % call['function']
+            for line in lines:
+                match = re.search(findPattern, line)
+                if match != None:
                     call['valid'] = 1
-                    break;
-                #endif
+                    call['reason'] = ''
+                    break
             #endfor
         #endif
     #endfor
 #enddef
+runtime = [0,1,2,3,4,5,6,7,8,9,10,11,12]
+runtime[0] = time.perf_counter_ns()
+runtime_text = ["Setup","Build callfile","Build call list","Index call list","Validate calls","Validation finished","Build report [invalid calls]","Sort invalid calls","Build report [location list]","Sort location list","Generate report file","Build report file","Report finished, all done"]
 
+assert (len(sys.argv) == 2 or len(sys.argv) == 3 or len(sys.argv) == 4), "usage:\ncallvalidator.py source=<src_input_dir> [file=<filename> | list=<listfilename>] [folder=<folder>]"
 
-assert len(sys.argv) == 2, "usage:\ntest_txtmerge.py <src_input_dir>"
+idir = str(sys.argv[1].replace("source=", ""))
 
-idir = str(sys.argv[1])
+if len(sys.argv) == 4:
+    vdir = str(sys.argv[3].replace("folder=", ""))
+else:
+    vdir = idir
 
-print("Start building call list: %s" % time.strftime("%H:%M:%S", time.localtime()))
+validationTarget = ''
+runtime[1] = time.perf_counter_ns()
+if len(sys.argv) > 2 and "file=" in str(sys.argv[2]):
+    validationTarget = sys.argv[2].replace("file=", "")
+    callFileList = [join(vdir, sys.argv[2].replace("file=", ""))]
+    validate = 'file'
+    
+if len(sys.argv) > 2 and "list=" in str(sys.argv[2]):
+    validationTarget = sys.argv[2].replace("list=", "")
+    callFileList = loadValidationList(join(sys.argv[3].replace("folder=", ""), sys.argv[2].replace("list=", "")))
+    validate = 'list'
+
+if validate == 'all':
+    validationTarget = idir
+    callFileList = [join(idir,f) for f in listdir(idir) if ".qsrc" in f]
 
-# grab the location files
-filelist = [f for f in listdir(idir) if ".qsrc" in f]
-buildlist_start = time.time()
 # build a list of all the calls happening
-for file in filelist:
-    with io.open(join(idir, file), 'rt', encoding='utf-8') as ifile:
+runtime[2] = time.perf_counter_ns()
+for file in callFileList:
+    with io.open(file, 'rt', encoding='utf-8') as ifile:
         lines = ifile.readlines()
-        processLines(lines)
-
-print("Finished building call list: %s" % time.strftime("%H:%M:%S", time.localtime()))
+        processLines(lines, ifile.name)
+    #endwith
+#endfor
+runtime[3] = time.perf_counter_ns()
+for call in callList:
+        call['callId'] = callList.index(call)
 
+runtime[4] = time.perf_counter_ns()
 # validating that all the calls are for valid locations
-for file in filelist:
-    with io.open(join(idir, file), 'rt', encoding='utf-8') as ifile:
-        lines = ifile.readlines()
-        validateCalls(lines)
+for file in calledFileList:
+    if file not in ['boyStat.qsrc', 'exp_gain.qsrc']:
+        try:
+            with io.open(join(idir, file), 'rt', encoding='utf-8') as ifile:
+                lines = ifile.readlines()
+                validateCalls(lines)
+        except IOError:
+            pass
+        #endwith
+    #endif
 #endfor
 
-print("Finished validation %s" % time.strftime("%H:%M:%S", time.localtime()))
-
+runtime[5] = time.perf_counter_ns()
 # create the call validity file and a list of files that call invalid locations
-oname = "call_validity.txt"
+timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+txtname = 'call_validity [%s] - %s.txt' % (validationTarget, time.strftime('%Y%m%d%H%M%S', time.localtime()))
+htmlname = 'call_validity [%s] - %s.html' % (validationTarget, time.strftime('%Y%m%d%H%M%S', time.localtime()))
+
+callheads = []
+callIds = []
+invalidCalls = []
+noInvLoc = 0
+noNonExistingLoc = 0
+noInvFun = 0
+noInvCall = 0
+noLocNeverCalled = len(neverCalledLocations)
+
+runtime[6] = time.perf_counter_ns()
+currLoc = ''
+for call in callList:
+    if call['valid'] == 0:
+        if currLoc != call['location']:
+            noInvLoc += 1
+            if ".qsrc doesn't exist" in call['reason']:
+                noNonExistingLoc += 1
+        callIds.append(call['callId'])
+        invalidCalls.append(call)
+    #enfif
+#endfor
+runtime[7] = time.perf_counter_ns()
+invalidCalls = sorted(invalidCalls, key=lambda k: (k['location'].lower(), k['function'].lower()))
+noInvFun = len(invalidCalls)
+
+runtime[8] = time.perf_counter_ns()
+for locationCall in locationCallList:
+    calls = locationCall['calls']
+    Ids = [call['callId'] for call in calls] 
+
+    if any(x in Ids for x in callIds):
+        callheads.append(locationCall)
+    #endfor
+#endfor
+
+runtime[9] = time.perf_counter_ns()
+callheads = sorted(callheads, key=lambda k: (k['calllocation'].lower()))
+noInvCall = len(callheads)
+
+runtime[10] = time.perf_counter_ns()
+location = ''
+txtInvalidLines = []
+for call in invalidCalls:
+    if location != '' and location.lower() != call['location'].lower():
+        txtInvalidLines.append('\n')
+
+    txtInvalidLines.append("    '%s', '%s' : %s\n" % (call['location'], call['function'], call['reason']))
+    location = call['location']
+#endfor
+
+txtLocationLines = []
+for head in callheads:            
+    txtLocationLines.append("  ---- %s [%s]:\n" % (head["calllocation"], head["fileName"]))
+    for call in head['calls']:
+        if call['callId'] in callIds:
+            target = callList[call['callId']]
+            txtLocationLines.append("    invalid call on line %04d: %s '%s', '%s'\t: %s\n" % (call['lineNo'], call['calltype'], target['location'], target['function'], target['reason']))
+        #endif
+    #endfor
+    txtLocationLines.append('\n')
+#endfor        
+
+runtime[11] = time.perf_counter_ns()
 try:
-    with io.open(oname, 'w', encoding='utf-8') as ofile: 
-        ofile.write("----- List of Invalid calls -----\n")
+    with io.open(txtname, 'w', encoding='utf-8') as ofile: 
+        ofile.write("----- Summary -----\n")
+        ofile.write("  Locations called incorrectly    : %03d\n" % noInvLoc)
+        ofile.write("  Non-existing locations called   : %03d\n" % noNonExistingLoc)
+        ofile.write("  Number of incorrect calls       : %03d\n" % noInvFun)
+        ofile.write("  Locations making incorrect calls: %03d\n" % noInvCall)
+        if validate == 'all':
+            ofile.write("  Locations never called          : %03d\n" % noLocNeverCalled)
         ofile.write("\n")
+        if validate == 'list':
+            ofile.write("----- Validated files -----\n")
+            if len(callFileList) > 10:
+                ofile.write("  The list contains %d files. Please see the list in %s.\n" % (len(callFileList), validationTarget))
+            else:                
+                for file in callFileList:
+                    ofile.write("  %s\n" % file)
+            #endif
+            ofile.write('\n')
+        #endif
 
-        for call in callList:
-            if call['valid'] == 0:
-                ofile.write("\t\t '%s', '%s' : invalid call\n" % (call['location'], call['function']) )
-        #endfor
+        ofile.write("----- List of Invalid calls -----\n")
+        ofile.write("\n")
+        
+        for line in txtInvalidLines:
+            ofile.write(line)
 
         ofile.write('\n')
 
         ofile.write("----- List of Locations and invalid calls they make -----\n")
         ofile.write('\n')
         
-        for locationCall in locationCallList:
-            headWritten = 0 
-            for callId in locationCall["callIds"]:
-                call = callList[callId]
-                if call["valid"] == 0:
-                    if headWritten == 0:
-                        ofile.write("\t---- %s:\n" % locationCall["calllocation"])
-                        headWritten = 1
-                    ofile.write("\t\t '%s', '%s' : invalid call\n" % (call['location'], call['function']) )
-            #endfor
-            if headWritten != 0:
-                ofile.write("\n")
-        #endfor
-    #endwith
+        for line in txtLocationLines:
+            ofile.write(line)
 
+        if validate == 'all':
+            ofile.write("----- List of Locations that are never called -----\n")
+
+            for line in neverCalledLocations:
+                ofile.write("%s\n" % line)                    
+
+    #endwith
 except IOError as e:
     raise SystemExit("ERROR: call validity file was not created! REASON: %s" % e.strerror)
 #endtry_except
 
-print("File saved finish: %s" % time.strftime("%H:%M:%S", time.localtime()))
+runtime[12] = time.perf_counter_ns()
+
+max = len(runtime)
+index = 0
+while index < max:
+    print("%s: %s" % (runtime_text[index], runtime[index]))
+    index += 1
+