44 Commity 1f6407542c ... 9f0b276362

Autor SHA1 Wiadomość Data
  Kevin_Smarts 9f0b276362 Merge remote-tracking branch 'Hooded_Silence/master' 3 miesięcy temu
  Kevin_Smarts ce1f3e4797 Merge remote-tracking branch 'Steuchs_bug_hunt/QSRC2TW' 3 miesięcy temu
  anjuna krokus c52957a3c2 [fixed] singular `'` introduced gamebreaking bug. Reported by Laxandros 3 miesięcy temu
  Myles Croft (Hooded Silence) 7df1622cda [Code updates] Remove ballet exploit, and amended text for clarity. Numerous minor changes to streamline ballet quests into the new journal quest layout that is in progress. 3 miesięcy temu
  Myles Croft (Hooded Silence) c077b26999 Merge branch 'master' of https://git.tfgames.site/Kevin_Smarts/glife 3 miesięcy temu
  Vengeance_11 586c67c0cb Updates to some porn NPCs 3 miesięcy temu
  Stephan Fuchs 8cb340bd1c [Revert] Replaces `exit-statements` with appropriate use of `else`-structures in `drugs`. 3 miesięcy temu
  Stephan Fuchs 4c7da755e4 [SugarCube] Changes the image at `start` to annoy a player who set up his images-folder with an appropriate message. 3 miesięcy temu
  Kevin_Smarts 6487248242 Merge remote-tracking branch 'Steuchs_bug_hunt/QSRC2TW' 3 miesięcy temu
  Kevin_Smarts c86487adf1 Merge remote-tracking branch 'Hooded_Silence/master' 3 miesięcy temu
  Kevin_Smarts fc7b073ec4 Merge branch 'master' of https://git.tfgames.site/Alaratt/glife 3 miesięcy temu
  Stephan Fuchs 99084d1c06 [Fix] Fixes willpower-call in `music_actions` 3 miesięcy temu
  Stephan Fuchs dfa48233ff [SugarCube] Adds `setup.qsp_strpos` 3 miesięcy temu
  Stephan Fuchs c21224004c [SugarCube] Fixes `00-prefix`-error. 3 miesięcy temu
  Stephan Fuchs 2d7b42d3b3 Merge remote-tracking branch 'kevinsmarts/master' into QSRC2TW 3 miesięcy temu
  Myles Croft (Hooded Silence) fdff0b43a7 Merge branch 'master' of https://git.tfgames.site/Kevin_Smarts/glife 3 miesięcy temu
  anjuna krokus 529c32b3ab Merge remote-tracking branch 'master/master' 3 miesięcy temu
  Myles Croft (Hooded Silence) 910ca1b944 [Code Review] Beta journal updated for peer review of code. As before use gs 'beta_journal_quests', 'init' to preview. 3 miesięcy temu
  bgkjdgbizgblzdgbr 16a1148da8 [fixed] More cut and paste error is the uni nursing program. 3 miesięcy temu
  Myles Croft (Hooded Silence) 181022b0d0 Merge branch 'master' of https://git.tfgames.site/Kevin_Smarts/glife 3 miesięcy temu
  anjuna krokus ac3fa5bf76 [fixed] not all attributes were set, which causes the "default" sport button to disappear 3 miesięcy temu
  anjuna krokus 482acc78ac Merge remote-tracking branch 'master/master' 3 miesięcy temu
  Stephan Fuchs 3c800b3df5 [SugarCube] Adds convert-mode `wardrobeItems`. 3 miesięcy temu
  Stephan Fuchs 044d58fec5 Merge remote-tracking branch 'kevinsmarts/master' into QSRC2TW 3 miesięcy temu
  anjuna krokus 937265fced [fixed] copy-paste error. Caught by Myles 3 miesięcy temu
  Stephan Fuchs 2fd913e41a Merge remote-tracking branch 'kevinsmarts/master' into QSRC2TW 3 miesięcy temu
  Myles Croft (Hooded Silence) 4d93027c2e Merge branch 'master' of https://git.tfgames.site/Kevin_Smarts/glife 3 miesięcy temu
  anjuna krokus d5aeb6b7b8 [fixed] cigarettes not being addictive if the cheat is off, and addictive when it's on. Reported by struckevaporate23. 3 miesięcy temu
  anjuna krokus aa07586f24 [changed] small code simplification 3 miesięcy temu
  Stephan Fuchs a690b11c5a [SugarCube] Fix deletion of mods not working in Chrome. 3 miesięcy temu
  Stephan Fuchs 2b2146ca01 [SugarCube] Adds Editor. 3 miesięcy temu
  Stephan Fuchs a748bce9f7 [SugarCube] Adds mod-support using `SweetCube`-functionality. 3 miesięcy temu
  Stephan Fuchs 9f1ac11948 [Sugarcube] Adds `setup.placeDiffInDom`. 3 miesięcy temu
  Stephan Fuchs a00628726c [SugarCube] Fixes gs in begin. 3 miesięcy temu
  Stephan Fuchs 86f09e8dc0 [SugarCube] Adds `setup.getPassageLinks` and `setup.getPassageLinksToPassage` 3 miesięcy temu
  Stephan Fuchs 29dc1c2b77 [SugarCube] Adds markup for Edit-button in Topbar 3 miesięcy temu
  Stephan Fuchs 725e564a64 [SugarCube] Adds `<<autocomplete>>`-macro to SC. 3 miesięcy temu
  anjuna krokus 2bd30f95ff [fixed] logic for sporting and loose outfits no longer working correctly due to an "or nude" clause instead of "and nude" clause. Reported by retlifeforme 3 miesięcy temu
  Stephan Fuchs 8cc8f95163 [qsrc2tw] Added `Ace` 3 miesięcy temu
  Stephan Fuchs 861a2bc3ee [qsrc2tw] Added `diff` 3 miesięcy temu
  Stephan Fuchs e01537b945 [qsrc2tw] Added jQueryUI 3 miesięcy temu
  Stephan Fuchs 9b73bfcd57 [qsrc2tw] Added loading of external code. 3 miesięcy temu
  Stephan Fuchs 32c7aa8ad5 [qsrc2tw] Fix `<<gt>>`-macro 3 miesięcy temu
  Stephan Fuchs aab5ad4145 [qsrc2tw] Updated storyformat to allow for modding of passages. 3 miesięcy temu
43 zmienionych plików z 981 dodań i 211 usunięć
  1. 207 49
      locations/beta_journal_quests.qsrc
  2. 87 70
      locations/drugs.qsrc
  3. 1 1
      locations/emp_functions.qsrc
  4. 1 6
      locations/hourly_events.qsrc
  5. 1 1
      locations/music_actions.qsrc
  6. 4 4
      locations/npcstatic4.qsrc
  7. 7 7
      locations/npcstatic5.qsrc
  8. 21 15
      locations/npcstatic6.qsrc
  9. 1 2
      locations/pirsingsalon.qsrc
  10. 9 9
      locations/pornfilm.qsrc
  11. 7 2
      locations/pushkin_ballet_class.qsrc
  12. 1 0
      locations/pushkin_ballet_evt.qsrc
  13. 2 1
      locations/pushkin_ballet_init.qsrc
  14. 9 3
      locations/pushkin_ballet_res.qsrc
  15. 38 11
      locations/quest_data_a274.qsrc
  16. 8 8
      locations/uni_admin.qsrc
  17. 8 3
      locations/wardrobe.qsrc
  18. 10 2
      qsrc2tw/package-lock.json
  19. 1 0
      qsrc2tw/package.json
  20. 4 3
      qsrc2tw/tools/QSRC2TW/index.js
  21. 5 0
      qsrc2tw/tools/QSRC2TW/resources/QSP-functions/strpos.js
  22. 1 1
      qsrc2tw/tools/QSRC2TW/resources/QSP-macros/GT.js
  23. 1 0
      qsrc2tw/tools/QSRC2TW/resources/resources/Topbar.css
  24. 8 0
      qsrc2tw/tools/QSRC2TW/resources/resources/Topbar.tw
  25. 4 2
      qsrc2tw/tools/QSRC2TW/src/visitor/QsrcVisitor.js
  26. 81 0
      qsrc2tw/tools/QSRC2TW/src/wardrobeItems.js
  27. 22 9
      qsrc2tw/tools/QSRC2TW/task_processor.js
  28. 0 0
      qsrc2tw/tools/tweeGo/storyFormats/sugarcube-2/format.js
  29. 81 0
      qsrc2tw/twine-code/editor/Editor.css
  30. 15 0
      qsrc2tw/twine-code/editor/Editor.js
  31. 121 0
      qsrc2tw/twine-code/editor/Editor.tw
  32. 35 0
      qsrc2tw/twine-code/editor/diff.js
  33. 30 0
      qsrc2tw/twine-code/editor/save.js
  34. 14 0
      qsrc2tw/twine-code/external/_external.ts
  35. 8 0
      qsrc2tw/twine-code/external/ace.ts
  36. 5 0
      qsrc2tw/twine-code/external/diff.ts
  37. 5 0
      qsrc2tw/twine-code/external/jQueryUI.ts
  38. 40 0
      qsrc2tw/twine-code/misc/getPassageLinks.ts
  39. 30 0
      qsrc2tw/twine-code/misc/head.txt
  40. 1 1
      qsrc2tw/twine-code/start/begin.tw
  41. 1 1
      qsrc2tw/twine-code/start/start.tw
  42. 10 0
      qsrc2tw/twine-code/twine-code.d.ts
  43. 36 0
      qsrc2tw/twine-code/ui/autoComplete.ts

+ 207 - 49
locations/beta_journal_quests.qsrc

@@ -11,13 +11,14 @@
 !! 💕 Relationship
 !! 📌 Location
 !! ✨ Magic
+!! 🔎 Hints
 !! Quest progress icons:
 !! <font color = "green">✓</font> - green tick
 !! <font color = "red">🗴</font> Red cross
 
 if $ARGS[0] = 'init':
 	*clr & cla
-	$loc_id = beta_journal_quests
+	$loc_id = 'beta_journal_quests'
 	act 'Put your journal down': gt $menu_loc, $menu_arg
 	act 'Return to top journal page': gt 'journal', 'records'
 	$jumploc = 'questtab'
@@ -27,6 +28,10 @@ if $ARGS[0] = 'init':
 		'<h2><font color = "red">Error with:</font> <<$debug[''journal'']>></h2>'
 		$debug['journal'] = ''
 	end
+		!! TEST
+		act 'Test vcard': gs $loc_id, 'vcard', 274
+		act 'Test Glossary': gs $loc_id, 'rel_pavlovsk'
+		!!TEST
 	if journal['alert'] = 1:
 		'<div>'
 		'<center><h3><font color = "orange">⚠ Todays Quests and Tasks</font></h3></center>'
@@ -43,7 +48,12 @@ if $ARGS[0] = 'init':
 	end
 end
 
+!! Friends and Relations
 if $ARGS[0] = 'rel_pavlovsk':
+	gs $loc_id, 'pavlovsk_array'
+	$table_gen_max = loc_gen
+	gs $loc_id, 'table_gen'
+
 end
 if $ARGS[0] = 'rel_city':
 end
@@ -53,7 +63,26 @@ if $ARGS[0] = 'rel_pushkin':
 	!! Ballet Maya
 end
 
+!! Game locations - quests
 if $ARGS[0] = 'geo_pavlovsk':
+	!!5/8 Estate
+	!!Commercial
+	!!Industrial
+	!!Market
+	!!Park
+	!!Train Station
+
+	if $ARGS[1] = '58_estate':
+		!!Parents apartment
+		!!Garages
+		!1Luda''s apartment
+		!!Shulgin''s Apartment
+	elseif $ARGS[1]= 'commercial':
+	elseif $ARGS[1]= 'industrial':
+	elseif $ARGS[1] = 'market':
+	elseif $ARGS[1] = 'park':
+	elseif $ARGS[1] = 'train_station':
+	end
 end
 if $ARGS[0] = 'geo_city':
 end
@@ -67,24 +96,40 @@ if $ARGS[0] = 'geo_village':
 end
 if $ARGS[0] = 'vcard':
 	*clr & cla
-	!! Section used to generate the user quests and other pertinent information
-	if $firstname['A<<ARGS[1]>>'] = '':
-		gs $loc_id, 'failure',  'id'
+	$quest_id = 'A' + ARGS[1]
+	$loc_id = 'beta_journal_quests'
+	!! Debug Section
+	if ARGS[1] = 0:
+		gt $loc_id, 'failure',  'id'
 	end
-	!! Initiate NPC data.
-	gs 'quest_data_a<<ARGS[1]>>', 'init'
-	$display_dob = func('shortgs', 'convert_dob', ARGS[1])
-
+		!! Initiate NPC data.
+	if $npc_quest['q_next'] = '':
+		!! qstage = current stage index
+		qstage = 1
+	end
+	gs 'quest_data_<<$quest_id>>', 'init'
+	!! Reset to correct location
+	$loc_id = 'beta_journal_quests'
+	!! Ensure quest data fields are populated
+	if $npc_quest['body'] ='':
+		gt $loc_id, 'failure', 'quest_body'
+	end
+	if $npc_quest['q_next'] = '':
+		gt $loc_id, 'failure', 'nav_forward'
+	end
+	if $npc_quest['q_back'] = '':
+		gt $loc_id, 'failure', 'nav_back'
+	end
+	!! Section used to generate the user quests and other pertinent information
 	!! Start vcard construction
-	$vard = ''
 	$vcard += '<center><h3>Ballet Quests - Characters</h3></center>'
 	$vcard += '<br>'
 	$vcard += '<div width="80%">'
-	$vcard += '<div style="width: 120px; padding: 0; float:left"><img style="height:100px;"  src="<<$npc_img_path[''A<<ARGS[1]>>'']>>/<<ARGS[1]>>_profile.jpg"></div>'
+	$vcard += '<div style="width: 120px; padding: 0; float:left"><img style="height:100px;"  src="<<$npc_img_path[''<<$quest_id>>'']>>/<<ARGS[1]>>_profile.jpg"></div>'
 	$vcard += '<div style="padding: 0;">'
-	$vcard += '<p><ul style="margin:0; padding:0;">Name: <<$npc_firstname[''A<<ARGS[1]>>'']>> "<<$npc_nickname[''A<<ARGS[1]>>'']>>" <<$npc_lastname[''A<<ARGS[1]>>'']>></ul>'
-	$vcard += '<ul style="margin:0; padding:0;">Date of Birth: <<$display_dob>> </ul>'
-	$vcard += '<ul style="margin:0; padding:0;">Home: <<$npc_home[''A<<ARGS[1]>>'']>></ul>'
+	$vcard += '<p><ul style="margin:0; padding:0;">Name: <<$npc_firstname[''<<quest_id>>'']>> "<<$npc_nickname[''<<$quest_id>>'']>>" <<$npc_lastname[''<<$quest_id>>'']>></ul>'
+	$vcard += '<ul style="margin:0; padding:0;">Date of Birth: ' + func('shortgs', 'convert_dob', ARGS[1])  +  ' </ul>'
+	$vcard += '<ul style="margin:0; padding:0;">Home: <<$npc_home[''<<$quest_id>>'']>></ul>'
 	$vcard += '<ul style="margin:0; padding:0;">Location: Unknown</ul>'
 
 	!! if debug is enabled show pop up msg:
@@ -99,41 +144,37 @@ if $ARGS[0] = 'vcard':
 	!! Output
 	$vcard
 
-	!! Ensure quest data fields are populated
-	if $npc_quest['q_body'] ='':
-		gs $loc_id, 'Failure', 'quest_body'
-	end
-	if $npc_quest['q_next'] = '':
-		gs $loc_id, 'Failure', 'nav_forward'
-	end
-	if $npc_quest['q_back'] = '':
-		gs $loc_id, 'Failure', 'nav_back'
-	end
-
 	!! Start quest body construction
 	$qsteps +=	'<div width = "80%">'
 	$qsteps +=	'<div style="padding: 10px;">'
-	$qsteps +=	'<h4>💕 Relationship Quest hints:</h4>'
-	$qsteps +=	$npc_quest['q_body']
+	$qsteps +=	'<h4>🔎 Quest hints:</h4>'
+	if journal_hints = 0:
+		$qsteps +=	'<a href="exec: journal_hints = 1 & gt ''<<$loc_id>>'', ''vcard'', <<ARGS[1]>>" >Enable hints</a><font color = "red"><b> Spoilers!</b></font> '
+	else
+		$qsteps +=	$npc_quest['hints']
+		$qsteps += '<br> <br>'
+		$qsteps +=	'<a href="exec: journal_hints = 0 & gt ''<<$loc_id>>'', ''vcard'', <<ARGS[1]>>">Disable hints</a> '
+	end
 	$qsteps +=	'<br>'
-	$qsteps +=	'<h4>Quest requisites:</h4>'
-	$qsteps +=	'<p><<$npc_[''quest_body'']>></p>'
+	$qsteps +=	'<h4>🧭 Quest requisites:</h4>'
+	$qsteps +=	'<p><<$npc_quest[''body'']>></p>'
 	$qsteps +=	'<br>'
 	$qsteps +=	'</div>'
 	$qsteps +=	'<div style="padding:5px; align: center;">'
 	$qsteps += 	'<center><h5>Quest History</h5></center>'
 
-	if $npc_quest['q_next'] ! 'null':
+	if $npc_quest['q_next'] = 'null':
 		$next_nav = 'Current Stage'
 	else
-		$next_nav = '<a href="gs ''quest_data_a<<ARGS[1]>>'', ''<<$npc_quest[''q_next'']>>''" >Next Stage</a> '
+		$next_nav = '<a href="gs ''<<$loc_id>>'', ''navigation'', ''next'' "" >Next Stage</a> <b>→</b>'
+		gs
 	end
-	if $npc_quest['q_back'] ! 'null':
+	if $npc_quest['q_back'] = 'null':
 		$back_nav = 'Quest Start'
 	else
-		$back_nav = '<a href="gs ''quest_data_a<<ARGS[1]>>'', ''<<$npc_quest[''q_next'']>>''" >Previous Stage</a> '
+		$back_nav = '<b>←</b> <a href="gs ''<<$loc_id>>'', ''navigation'', ''back'' " >Previous Stage</a> '
 	end
-	$qsteps +=	'<center><b>←</b> <<$back_nav>> |  <<$next_nav>> <b>→</b></center>'
+	$qsteps +=	'<center><<$back_nav>> | <<$next_nav>></center>'
 	$qsteps +=	'</div>'
 	$qsteps +=	'</div>'
 	$qsteps +=	'<br>'
@@ -145,42 +186,159 @@ if $ARGS[0] = 'vcard':
 	!! Clean up
 	killvar '$vcard'
 	killvar '$qsteps'
-	killvar 'birthday'
-	killvar '$birthday'
-	killvar 'birthmonth'
-	killvar '$birthmonth'
-	killvar 'birthyear'
+	killvar 'quest_id'
 	killvar '$evt_suffix'
 end
 
+!! Navigation
+if $ARGS[0] = 'navigation':
+	$nav_click = $ARGS[1]
+	if $ARGS[1] ! '' and qstage = 1:
+		$npc_quest['q_back'] = 'null'
+	elseif qstage > 1 and $nav_click = 'next':
+		qstage += 1
+	elseif qstage >= 2 and $nav_click ='back':
+		qstage -= 1
+	else
+		$debug['journal'] = 'Navigation failed to be set.'
+	end
+	killvar '$nav_click'
+	gs 'quest_data_<<$quest_id>>', 'init'
+	gs 'beta_journal_quests', 'init'
+end
+
 if $ARGS[0] = 'failure':
 	!! Debug sections
 	if $ARGS[1] = 'id':
 		$debug['journal'] = 'NPC ID not set, vcard not generated.'
-		gt $loc_id, 'start'
 	elseif $ARGS[1] = 'quest_body':
-		$debug['journal'] = 'Quest body not set, quests details was not display.'
+		$debug['journal'] = 'Quest body not set, quests details was not set.'
 	elseif $ARGS[1] = 'nav_forward':
 		$debug['journal'] = 'No forward navigation set - please ensure you have set the var in quest_data'
 	elseif $ARGS[1] = 'nav_back':
 		$debug['journal'] = 'No back navigation set - please ensure you have set the var in quest_data'
 	end
+	'vcard failed to initialise: ' + $debug['journal']
 end
 
 if $ARGS[0] = 'gametips':
 
-	if ARGS[1] = 1:
+	if $ARGS[1] = '1':
 		'If you have 50 skill in modern dance and Albina likes you might get a chance to join Starlets.'
-	elseif ARGS[1] = 2:
+	elseif $ARGS[1] = '2':
 		'Mon Cheri is the most prestigious clothing store in St. Petersburg, with a price tag to match.'
-	elseif ARGS[1] = 3:
+	elseif $ARGS[1] = '3':
 		'There is some parts of the game restricted to over-18s such as doing driving lessons, gambling at the casino and other areas. There is rumours that there is studios who are less fussy about sticking to the law.'
-	elseif ARGS[1] = 4:
-	elseif ARGS[1] = 5:
-	elseif ARGS[1] = 6:
-	elseif ARGS[1] = 7:
-	elseif ARGS[1] = 8:
-	elseif ARGS[1] = 9:
+	elseif $ARGS[1] = '4':
+	elseif $ARGS[1] = '5':
+	elseif $ARGS[1] = '6':
+	elseif $ARGS[1] = '7':
+	elseif $ARGS[1] = '8':
+	elseif $ARGS[1] = '9':
 	end
 end
+
+!! Table Generator for npcs and locations
+
+if $ARGS[0] = 'table_gen':
+
+	!! Original code by Anjuna
+	entry_counter_i = 1
+	entry_counter_j = 1
+	table_counter = 0
+	if ARGS[1] = 0:
+		table_columns = 3
+	else
+		table_columns = ARGS[1]
+	end
+
+	$bjq_temp_table = '<center><table cellspacing="3" bgcolor="<<$theme[''table_bg_alt'']>>" width="80%" align="center">'
+
+	:jmp_table_gen
+						!! CREATE ROW
+
+		$bjq_temp_table +=	'<tr width="100px">'
+		:jmp_table_gen2
+							!! CREATE CELL
+			$bjq_temp_table +=		'<td align="left">'
+			$bjq_temp_table +=			'<a href="exec: gt ''<<$loc_id>>'' ,''<<$loc_shortname[entry_counter_i]>>''">'
+			$bjq_temp_table +=				'<img height="100" src="<<$loc_path[entry_counter_i]>>">'
+			$bjq_temp_table +=			'</a>'
+			$bjq_temp_table += 		'</td>'
+							!! END CELL
+			entry_counter_i += 1
+		if entry_counter_i <= table_gen_max and (entry_counter_i mod table_columns) ! 0: jump 'jmp_table_gen2'
+		$bjq_temp_table +=	'</tr>'
+						!! END ROW
+
+						!! CREATE ROW
+		$bjq_temp_table +=	'<tr width="100px">'
+		:jmp_table_gen3
+								!! CREATE CELL
+			$bjq_temp_table += 		'<td align="left">'
+			$bjq_temp_table +=			$loc_name[entry_counter_j]
+			$bjq_temp_table +=		'</td>'
+								!! END CELL
+			entry_counter_j += 1
+		if entry_counter_j <= table_gen_max and (entry_counter_j mod table_columns) ! 0: jump 'jmp_table_gen3'
+		$bjq_temp_table +=	'</tr>'
+						!! END ROW
+
+		table_counter += 1
+		if table_counter = 5:
+						!! ADD BLANK ROW
+			$bjq_temp_table += '<tr></tr>'
+			table_counter = 0
+		end
+
+	if entry_counter_i < table_gen_max: jump 'jmp_table_gen'
+
+	$bjq_temp_table += '</table></center>'
+	'<<$bjq_temp_table>>'
+
+	killvar '$bjq_temp_table'
+	killvar 'entry_counter_i'
+	killvar 'entry_counter_j'
+	killvar 'table_columns'
+	killvar 'table_counter'
+	killvar 'table_gen_max'
+end
+
+!! Set up locations for image paths for the loop
+if $ARGS[0] = 'pavlovsk_array':
+	!! Set up locations for image paths for the loop
+	loc_gen = 1
+	!! Display Name
+	$loc_name[loc_gen] = 'Five Eight Estate'
+	!! $args[1] function name to show data
+	$loc_shortname[loc_gen] = '58_estate'
+	!! default game image file path
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/resident/apartment/complex.jpg'
+	!! Area description to indicate what is in this area.
+	$loc_description[loc_gen] = 'Five Eight Estate where your parents and aunt Luda live. There is also the garage that your father hires to fix his car.'
+
+	!$loc_path[loc_gen] =
+
+	loc_gen += 1
+	$loc_name[loc_gen] = 'Commercial Area'
+	$loc_shortname[loc_gen] = 'commercial'
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/gorodok.jpg'
+	$loc_description[loc_gen] = ''
+	loc_gen += 1
+	$loc_name[loc_gen] = 'Industrial Area'
+	$loc_shortname[loc_gen] = 'industrial'
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/factory/pav_factory.jpg'
+	loc_gen += 1
+	$loc_name[loc_gen] = 'Pavlovsk Market'
+	$loc_shortname[loc_gen] = 'market'
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/pav_market_day.jpg'
+	loc_gen += 1
+	$loc_name[loc_gen] = 'Pavlovsk Park'
+	$loc_shortname[loc_gen] = 'park'
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/park/skver.jpg'
+	loc_gen += 1
+	$loc_name[loc_gen] = 'Train Station'
+	$loc_shortname[loc_gen] = 'train_station'
+	$loc_path[loc_gen] = 'images/locations/pavlovsk/trainstation/vokzal.jpg'
+end
 --- beta_journal_quests ---------------------------------

+ 87 - 70
locations/drugs.qsrc

@@ -24,7 +24,6 @@ if $ARGS[0] = 'cikl':
 	gs 'drugs', 'aphrodisiac', 'cikl'
 	gs 'drugs', 'hair_extensioncream', 'cikl'
 	gs 'drugs', 'butt_injection', 'cikl'
-
 elseif $ARGS[0] = 'hourly_events':
 	gs 'drugs', 'smoke', 'hourly_events'
 	gs 'drugs', 'joint', 'hourly_events'
@@ -32,13 +31,11 @@ elseif $ARGS[0] = 'hourly_events':
 	gs 'drugs', 'cocaine', 'hourly_events'
 	gs 'drugs', 'amphetamine', 'hourly_events'
 	gs 'drugs', 'aphrodisiac', 'hourly_events'
-
 elseif $ARGS[0] = 'stat':
 	gs 'drugs', 'heroin', 'stat'
 	gs 'drugs', 'alcohol', 'stat'
 	gs 'drugs', 'cocaine', 'stat'
 	gs 'drugs', 'amphetamine', 'stat'
-
 elseif $ARGS[0] = 'pain_relief':
 	if alko > 9:
 		pain['relief'] = 70
@@ -55,12 +52,12 @@ elseif $ARGS[0] = 'pain_relief':
 	elseif pain['killer'] > 12 and alko <= 9:
 		pain['relief'] = 50
 	end
-
-
 elseif $ARGS[0] = 'smoke':
 	if $ARGS[1] = 'hourly_events':
-		if drugVars['cigarettes_used'] >= 20 and cheatVars['drugs_immune'] = 0: drugVars['cigarettes_need'] += 1
-		if drugVars['cigarettes_need'] > 10 and InSleep = 0 and pcs_mood > 20 and cheatVars['drugs_immune'] = 0: pcs_mood -= pcs_mood / 10
+		if cheatVars['drugs_immune'] = 0:
+			if drugVars['cigarettes_used'] >= 20: drugVars['cigarettes_need'] += 1
+			if drugVars['cigarettes_need'] > 10 and InSleep = 0 and pcs_mood > 20: pcs_mood -= pcs_mood / 10
+		end
 
 		if drugVars['cigarettes_need'] > 300:
 			drugVars['cigarettes_need'] = 0
@@ -72,7 +69,7 @@ elseif $ARGS[0] = 'smoke':
 			if mc_inventory['cigarettes'] <= 0: mc_inventory['cigarettes'] = 0 & msg 'That was your last cigarette.'
 		end
 
-		if cheatVars['drugs_immune'] = 1:
+		if cheatVars['drugs_immune'] = 0:
 			drugVars['cigarettes_used'] += 1
 			if drugVars['cigarettes_used'] > 20 and drugVars['cigarettes_exp'] = 0: drugVars['cigarettes_exp'] = 1
 		end
@@ -98,7 +95,6 @@ elseif $ARGS[0] = 'smoke':
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'joint':
 	if $ARGS[1] = 'hourly_events':
 		if drugVars['weed_high'] > 0: drugVars['weed_high'] -= 1
@@ -136,7 +132,6 @@ elseif $ARGS[0] = 'joint':
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'heroin':
 	if $ARGS[1] = 'hourly_events':
 		if drugVars['heroin_high'] > 0:
@@ -165,6 +160,7 @@ elseif $ARGS[0] = 'heroin':
 			drugVars['heroin_penalty'] += 1
 		end
 	else
+
 		if cheatVars['drugs_immune'] = 0:
 			drugVars['heroin_used'] += 1
 			if drugVars['heroin_used'] > 1 and drugVars['heroin_exp'] = 0: drugVars['heroin_exp'] = 1
@@ -178,7 +174,6 @@ elseif $ARGS[0] = 'heroin':
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'cocaine':
 	if $ARGS[1] = 'cikl':
 		if drugVars['cocaine_system'] > 60:
@@ -202,16 +197,18 @@ elseif $ARGS[0] = 'cocaine':
 	elseif $ARGS[1] = 'stat':
 		if cheatVars['drugs_immune'] = 1:
 			if drugVars['cocaine_addict'] ! 0: drugVars['cocaine_addict'] = 0
-		elseif drugVars['cocaine_system'] >= 30 and drugVars['cocaine_addict'] = 0 and cheatVars['drugs_immune'] = 0:
+		elseif drugVars['cocaine_system'] >= 30 and drugVars['cocaine_addict'] = 0:
 			drugVars['cocaine_addict'] = 1
 		elseif drugVars['cocaine_system'] = 0 and drugVars['cocaine_addict'] = 1:
 			drugVars['cocaine_addict'] = 0
 		end
 	else
+
 		if ARGS[1] = 0 and $ARGS[1] = '':
 			mc_inventory['cocaine'] -= 1
 			if mc_inventory['cocaine'] <= 0: mc_inventory['cocaine'] = 0 & msg 'That was your last line of cocaine.'
 		end
+
 		if cheatVars['drugs_immune'] = 0:
 			drugVars['cocaine_used'] += 1
 			if drugVars['cocaine_used'] > 3 and drugVars['cocaine_exp'] = 0: drugVars['cocaine_exp'] = 1
@@ -227,7 +224,6 @@ elseif $ARGS[0] = 'cocaine':
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'amphetamine':
 	if $ARGS[1] = 'hourly_events':
 		if insleep = 1:
@@ -291,28 +287,28 @@ elseif $ARGS[0] = 'amphetamine':
 			end
 			killvar 'temp_addictChance'
 		end
+
+	elseif drugVars['amphetamine_intake'] >= 2:
+		'Your heart is already beating uncontrollably in your chest, you should avoid taking anymore pills.'
 	else
-		if drugVars['amphetamine_intake'] >= 2:
-			'Your heart is already beating uncontrollably in your chest, you should avoid taking anymore pills.'
-		else
-			'<font color= blue>You swallow the white pill.</font>'
 
-			if ARGS[1] = 0 and $ARGS[1] = '':
-				mc_inventory['amphetamine'] -= 1
-				if mc_inventory['amphetamine'] <= 0: mc_inventory['amphetamine'] = 0 & msg 'That was your last amphetamine pill.'
-			end
-			if cheatVars['drugs_immune'] = 0:
-				drugVars['amphetamine_used'] += 1
-				if drugVars['amphetamine_used'] > 5 and drugVars['amphetamine_exp'] = 0: drugVars['amphetamine_exp'] = 1
-			end
+		'<font color= blue>You swallow the white pill.</font>'
+
+		if ARGS[1] = 0 and $ARGS[1] = '':
+			mc_inventory['amphetamine'] -= 1
+			if mc_inventory['amphetamine'] <= 0: mc_inventory['amphetamine'] = 0 & msg 'That was your last amphetamine pill.'
+		end
 
-			drugVars['amphetamine_intake'] += 1
-			drugVars['amphetamine_high'] = 12
+		if cheatVars['drugs_immune'] = 0:
+			drugVars['amphetamine_used'] += 1
+			if drugVars['amphetamine_used'] > 5 and drugVars['amphetamine_exp'] = 0: drugVars['amphetamine_exp'] = 1
 		end
+
+		drugVars['amphetamine_intake'] += 1
+		drugVars['amphetamine_high'] = 12
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'mentats':
 	if $ARGS[1] = 'cikl':
 		if drugVars['mentats_dose'] = 1:
@@ -322,16 +318,20 @@ elseif $ARGS[0] = 'mentats':
 			drugVars['mentats_dose'] = 0
 		end
 	else
+
 		if ARGS[1] = 0 and $ARGS[1] = '':
 			mc_inventory['mentats'] -= 1
 			if mc_inventory['mentats'] <= 0: mc_inventory['mentats'] = 0 & msg 'That was your last neurobooster pill.'
 		end
-		drugVars['mentats_used'] += 1
+
+		if cheatVars['drugs_immune'] = 0:
+			drugVars['mentats_used'] += 1
+		end
+
 		drugVars['mentats_dose'] += 1
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'steroids':
 	if $ARGS[1] = 'cikl':
 		if drugVars['steroids_dose'] >= 1:
@@ -341,21 +341,24 @@ elseif $ARGS[0] = 'steroids':
 			end
 			drugVars['steroids_dose'] = 0
 		end
+
+	elseif drugVars['steroids_dose'] >= 3:
+		'You really shouldn''t take any more pills today.'
 	else
-		if drugVars['steroids_dose'] < 3:
-			'<font color = blue>You swallow the orange pill.</font>'
+		'<font color = blue>You swallow the orange pill.</font>'
 
-			if ARGS[1] = 0 and $ARGS[1] = '':
-				mc_inventory['steroids'] -= 1
-				if mc_inventory['steroids'] <= 0: mc_inventory['steroids'] = 0 & msg 'That was your last steroid pill.'
-			end
+		if ARGS[1] = 0 and $ARGS[1] = '':
+			mc_inventory['steroids'] -= 1
+			if mc_inventory['steroids'] <= 0: mc_inventory['steroids'] = 0 & msg 'That was your last steroid pill.'
+		end
 
+		if cheatVars['drugs_immune'] = 0:
 			drugVars['steroids_used'] += 1
-			drugVars['steroids_dose'] += 1
-		else
-			'You really shouldn''t take any more pills today.'
 		end
+
+		drugVars['steroids_dose'] += 1
 		gs 'stat'
+
 	end
 
 
@@ -373,31 +376,35 @@ elseif $ARGS[0] = 'breastcream':
 			end
 			killvar 'temp'
 		end
+	elseif drugVars['breastcream_dose'] >= 1:
+		'Using any more cream won''t have any effect.'
 	else
-		if drugVars['breastcream_dose'] < 1:
-			'<font color = #DB7093>You smear the cream onto your breasts and rub it in.</font>'
 
-			if ARGS[1] = 0 and $ARGS[1] = '':
-				mc_inventory['breastcream'] -= 1
-				if mc_inventory['breastcream'] <= 0: mc_inventory['breastcream'] = 0 & msg 'That was your last bit of breast cream.'
-			end
+		'<font color = #DB7093>You smear the cream onto your breasts and rub it in.</font>'
 
+		if ARGS[1] = 0 and $ARGS[1] = '':
+			mc_inventory['breastcream'] -= 1
+			if mc_inventory['breastcream'] <= 0: mc_inventory['breastcream'] = 0 & msg 'That was your last bit of breast cream.'
+		end
+
+		if cheatVars['drugs_immune'] = 0:
 			drugVars['breastcream_used'] += 1
-			drugVars['breastcream_dose'] = 1
-		else
-			'Using any more cream won''t have any effect.'
 		end
+
+		drugVars['breastcream_dose'] = 1
 		gs 'stat'
 	end
 
-
 elseif $ARGS[0] = 'painkiller':
 	if ARGS[1] = 0 and $ARGS[1] = '':
 		mc_inventory['painkillers'] -= 1
 		if mc_inventory['painkillers'] <= 0: mc_inventory['painkillers'] = 0 & msg 'That was your last painkiller.'
 	end
 
-	drugVars['painkillers_used'] += 1
+	if cheatVars['drugs_immune'] = 0:
+		drugVars['painkillers_used'] += 1
+	end
+
 	pain['killer'] += 1
 	gs 'stat'
 
@@ -412,6 +419,7 @@ elseif $ARGS[0] = 'alcohol':
 			pain['relief'] = 15
 		end
 	else
+
 		if cheatVars['drugs_immune'] = 0:
 			drugVars['alcohol_used'] += 1
 			if drugVars['alcohol_used'] > 15 and drugVars['alcohol_exp'] = 0: drugVars['alcohol_exp'] = 1
@@ -529,13 +537,17 @@ elseif $ARGS[0] = 'aphrodisiac':
 	else
 		if drugVars['aphrodisiac_overdose'] = 1:
 			$drugVars['aphrodisiac_msg'] = '<br>You''ve had enough aphrodisiac for today.'
+
 		else
+
 			if ARGS[1] = 0 and $ARGS[1] = '':
 				mc_inventory['aphrodisiac'] -= 1
 				if mc_inventory['aphrodisiac'] <= 0: mc_inventory['aphrodisiac'] = 0 & msg 'That was your last aphrodisiac pill.'
 			end
 
-			drugVars['aphrodisiac_used'] += 1
+			if cheatVars['drugs_immune'] = 0:
+				drugVars['aphrodisiac_used'] += 1
+			end
 
 			if drugVars['aphrodisiac_timer'] = 0:
 				$drugVars['aphrodisiac_msg'] = '<font color = #DB7093><br>You take a gum and chew it. It tastes like strawberry, but is also kind of spicy.</font>'
@@ -570,8 +582,8 @@ elseif $ARGS[0] = 'aphrodisiac':
 			else
 				$drugVars['aphrodisiac_msg'] = '<font color = #DB7093>You chew another gum with trepidation, looking forward to more orgasms but nothing happens. Huh. Have you become immune?</font>'
 			end
+			gs 'stat'
 		end
-		gs 'stat'
 	end
 
 
@@ -585,20 +597,22 @@ elseif $ARGS[0] = 'hair_extensioncream':
 				'Feels like your hair has grown slightly.'
 			end
 		end
+	elseif drugVars['hair_extensioncream_dose'] >= 1:
+		'Using any more hair extension shampoo won''t have any effect.'
 	else
-		if drugVars['hair_extensioncream_dose'] < 1:
-			'<font color = #DB7093>You smear the shampoo into your hair and rub it in, then wash it out shortly later.</font>'
 
-			if ARGS[1] = 0 and $ARGS[1] = '':
-				mc_inventory['hair_extensioncream'] -= 1
-				if mc_inventory['hair_extensioncream'] <= 0: mc_inventory['hair_extensioncream'] = 0 & msg 'That was your last bit of hair extension shampoo.'
-			end
+		'<font color = #DB7093>You smear the shampoo into your hair and rub it in, then wash it out shortly later.</font>'
+
+		if ARGS[1] = 0 and $ARGS[1] = '':
+			mc_inventory['hair_extensioncream'] -= 1
+			if mc_inventory['hair_extensioncream'] <= 0: mc_inventory['hair_extensioncream'] = 0 & msg 'That was your last bit of hair extension shampoo.'
+		end
 
+		if cheatVars['drugs_immune'] = 0:
 			drugVars['hair_extensioncream_used'] += 1
-			drugVars['hair_extensioncream_dose'] = 1
-		else
-			'Using any more hair extension shampoo won''t have any effect.'
 		end
+
+		drugVars['hair_extensioncream_dose'] = 1
 		gs 'stat'
 	end
 
@@ -617,21 +631,24 @@ elseif $ARGS[0] = 'butt_injection':
 			end
 			killvar 'temp'
 		end
+	elseif drugVars['butt_injection_dose'] >= 1:
+		'Using any more injections won''t have any effect.'
 	else
-		if drugVars['butt_injection_dose'] < 1:
-			'<font color = #DB7093>You inject the KBI formula into your ass.</font>'
 
-			if ARGS[1] = 0 and $ARGS[1] = '':
-				mc_inventory['butt_injection'] -= 1
-				if mc_inventory['butt_injection'] <= 0: mc_inventory['butt_injection'] = 0 & msg 'That was your last KBI shot.'
-			end
+		'<font color = #DB7093>You inject the KBI formula into your ass.</font>'
+
+		if ARGS[1] = 0 and $ARGS[1] = '':
+			mc_inventory['butt_injection'] -= 1
+			if mc_inventory['butt_injection'] <= 0: mc_inventory['butt_injection'] = 0 & msg 'That was your last KBI shot.'
+		end
 
+		if cheatVars['drugs_immune'] = 0:
 			drugVars['butt_injection_used'] += 1
-			drugVars['butt_injection_dose'] = 1
-		else
-			'Using any more injections won''t have any effect.'
 		end
+
+		drugVars['butt_injection_dose'] = 1
 		gs 'stat'
+
 	end
 
 

+ 1 - 1
locations/emp_functions.qsrc

@@ -63,7 +63,7 @@ if $ARGS[0] = 'gen_schedule':
 			$tableheader += '<th style="padding: 10px;"><font color="<<$font_theme>>">' + iif(display_hour < 10, '0<<display_hour >>', display_hour) + ':00</font></th>'
 		elseif header_switch=2:
 			header_switch = 1
-			$tableheader += '<th style="padding: 10px;"><font color="<<$font_theme>>">' + iif(display_hour < 10, '0<< display_hour>>', display_hour) + ':30</font></th>'
+			$tableheader += '<th style="padding: 10px;"><font color="<<$font_theme>>">' + iif(display_hour < 10, '0<<display_hour>>', display_hour) + ':30</font></th>'
 		end
 		i_hour += 1
 	if i_hour <= mod_max_hour: jump 'jmp_header_create'

+ 1 - 6
locations/hourly_events.qsrc

@@ -96,12 +96,7 @@ else
 	pcs_willpower_feeder = pcs_willpower_feeder mod 100
 end
 
-gs 'drugs', 'smoke', 'hourly_events'
-gs 'drugs', 'joint', 'hourly_events'
-gs 'drugs', 'heroin', 'hourly_events'
-gs 'drugs', 'cocaine', 'hourly_events'
-gs 'drugs', 'amphetamine', 'hourly_events'
-gs 'drugs', 'aphrodisiac', 'hourly_events'
+gs 'drugs', 'hourly_events'
 
 
 !!=======================================================!!

+ 1 - 1
locations/music_actions.qsrc

@@ -331,7 +331,7 @@ if $ARGS[0] = 'willpower_cost':
         else
             $diff = 'easy'
         end
-        gs 'willpower', 'skill', 'self', pcs_perform, $diff
+        gs 'willpower', 'skill', 'self', 'pcs_perform', $diff
     end
 end
 

+ 4 - 4
locations/npcstatic4.qsrc

@@ -900,8 +900,8 @@ $npc_firstname['A<<npctemp>>'] = 'Alexander'
 $npc_nickname['A<<npctemp>>'] = 'Alexei'
 $npc_lastname['A<<npctemp>>'] = 'Radimov'
 $npc_usedname['A<<npctemp>>'] = 'Porn actor Alexei Radimov'
-$npc_notes['A<<npctemp>>'] = 'Alexei has worked in porn ever since he lost his job as a steel worker. He is divorced with twin teenage daughters and only planned to do porn as a temporary thing to pay for their university studies, but eventually chose to make it permanent since it earned him more money than any other job could offer. He is sellable too, being almost two meters tall and built like a tank.'
-npc_dob['A<<npctemp>>'] = 19721110
+$npc_notes['A<<npctemp>>'] = 'Alexei is a former steel plant worker. He is divorced with twin teenage daughters and ended up doing porn to pay for their university studies since it earned him more money than any other job could offer. He is sellable too, being almost two meters tall and built like a tank.'
+npc_dob['A<<npctemp>>'] = 19710610
 npc_gender['A<<npctemp>>'] = 0
 
 gs 'npcstaticdefaults', 'defaults'
@@ -918,7 +918,7 @@ npc_spermpot['A<<npctemp>>'] = 12000
 npctemp = 194
 $npc_dna['A<<npctemp>>'] = '7008670756 7958693370 7059741341 1566986214 1732880506 1281239619 1634169768'
 $npc_firstname['A<<npctemp>>'] = 'Sergei'
-$npc_nickname['A<<npctemp>>'] = 'Seryozha'
+$npc_nickname['A<<npctemp>>'] = 'Sergei'
 $npc_lastname['A<<npctemp>>'] = 'Tatarov'
 $npc_usedname['A<<npctemp>>'] = 'Porn actor Sergei Tatarov'
 $npc_notes['A<<npctemp>>'] = 'Sergei is smooth, charming and handsome, but a real asshole. Nobody likes to work with him, but he is a true professional and a really good actor. There are rumors about him raping a schoolgirl, but nobody knows anything about it.'
@@ -938,7 +938,7 @@ npc_spermpot['A<<npctemp>>'] = 10000
 npctemp = 195
 $npc_dna['A<<npctemp>>'] = '1086487692 7476661390 7698010724 1870038241 1870978496 1236988759 1677200479'
 $npc_firstname['A<<npctemp>>'] = 'Egor'
-$npc_nickname['A<<npctemp>>'] = 'Egori'
+$npc_nickname['A<<npctemp>>'] = 'Egor'
 $npc_lastname['A<<npctemp>>'] = 'Klyuyev'
 $npc_usedname['A<<npctemp>>'] = 'Porn actor Egor Klyuyev'
 $npc_notes['A<<npctemp>>'] = 'In his early 50s, Egor is the oldest and most experienced actor at the porn studio. He''s living a dream life of being paid to fuck hot girls all day long, a fact he likes to proudly boast about to anyone who listens.'

+ 7 - 7
locations/npcstatic5.qsrc

@@ -72,7 +72,7 @@ $npc_dna['A<<npctemp>>'] = '7086114441 7277581517 7759004439 7806044180 78472404
 $npc_firstname['A<<npctemp>>'] = 'Rozalina'
 $npc_nickname['A<<npctemp>>'] = 'Roza'
 $npc_lastname['A<<npctemp>>'] = 'Harkov'
-$npc_usedname['A<<npctemp>>'] = 'Porn actress Scarlett Rose'
+$npc_usedname['A<<npctemp>>'] = 'Scarlett Rose'
 $npc_notes['A<<npctemp>>'] = 'Roza and her older brother Vasya are both in the porn business, "agreeing" to do it after she was raped for late repayment of her debt. She dropped out of university where she was learning to be a doctor to do porn, hoping to get the debt hunters off her back as soon as she can.'
 npc_dob['A<<npctemp>>'] = 19970202
 npc_gender['A<<npctemp>>'] = 1
@@ -686,11 +686,11 @@ npc_dick['A<<npctemp>>'] = 16
 
 npctemp = 234
 $npc_dna['A<<npctemp>>'] = '9695699672 2188071337 5246878581 9504515633 1030174716 8079090096 1524386291'
-$npc_firstname['A<<npctemp>>'] = 'Eleanor'
-$npc_nickname['A<<npctemp>>'] = 'Ellie'
-$npc_lastname['A<<npctemp>>'] = 'Bishop'
-$npc_usedname['A<<npctemp>>'] = 'Ellie Knight'
-$npc_notes['A<<npctemp>>'] = 'An American exchange student who does porn to pay her way through life. The fact that she''s American makes her unpopular with her co-stars, but she makes up for this by being good at her job.'
+$npc_firstname['A<<npctemp>>'] = 'Ashley'
+$npc_nickname['A<<npctemp>>'] = 'Ash'
+$npc_lastname['A<<npctemp>>'] = 'Wells'
+$npc_usedname['A<<npctemp>>'] = 'Ash Lee'
+$npc_notes['A<<npctemp>>'] = 'An American student on a gap year who is doing porn to fund her current lifestyle. She''s considered a ''forbidden fruit'' by her male co-stars, but is unpopular amongst the female stars.'
 npc_dob['A<<npctemp>>'] = 19961209
 npc_gender['A<<npctemp>>'] = 1
 
@@ -749,7 +749,7 @@ $npc_firstname['A<<npctemp>>'] = 'Aliana'
 $npc_nickname['A<<npctemp>>'] = 'Alli'
 $npc_lastname['A<<npctemp>>'] = 'Smirnova'
 $npc_usedname['A<<npctemp>>'] = 'Alli Smirnova'
-$npc_notes['A<<npctemp>>'] = 'A teen who is obsessed with porn. Against her parents wishes, she joined the studio on her 18th birthday and is always eager to get on camera. Her young age and attractive appearance gives her a lot of age play roles and makes her extremely popular with her male co-stars.'
+$npc_notes['A<<npctemp>>'] = 'A sex obessed teen who, against her parents wishes, went into porn instead of attending university. Always eager to get on camera, her young age and attractive appearance gives her a lot of age play roles and makes her extremely popular with her male co-stars.'
 npc_dob['A<<npctemp>>'] = 19980523
 npc_gender['A<<npctemp>>'] = 1
 

+ 21 - 15
locations/npcstatic6.qsrc

@@ -359,7 +359,7 @@ $npc_dna['A<<npctemp>>'] = '0'
 $npc_firstname['A<<npctemp>>'] = 'Mia'
 $npc_nickname['A<<npctemp>>'] = 'Mia'
 $npc_lastname['A<<npctemp>>'] = 'Radimova'
-$npc_notes['A<<npctemp>>'] = 'The elder of the identical twins studying nursing at the university. She and Yana are inseparable and are seen almost everywhere together. Like her younger sister, she enjoys playing pranks on her professors and classmates and causing confusion about who is actually who. Her parents are divorced, but her father pays for her tuition. There is a rumor spreading across campus claiming that he is a porn star.'
+$npc_notes['A<<npctemp>>'] = 'The elder of the identical twins studying nursing at the university. She and Yana are inseparable and are seen almost everywhere together. Like her younger sister, she enjoys playing pranks on her professors and classmates and causing confusion about who is actually who. Her parents are divorced, but her father pays for her tuition. There is a rumor spreading across campus claiming that he is a porn actor.'
 npc_dob['A<<npctemp>>'] = 19980325
 npc_gender['A<<npctemp>>'] = 1
 
@@ -379,7 +379,7 @@ $npc_dna['A<<npctemp>>'] = '0'
 $npc_firstname['A<<npctemp>>'] = 'Yana'
 $npc_nickname['A<<npctemp>>'] = 'Yana'
 $npc_lastname['A<<npctemp>>'] = 'Radimova'
-$npc_notes['A<<npctemp>>'] = 'The younger of the identical twins studying nursing at the university. She and Mia are inseparable and are seen almost everywhere together. Like her older sister, she enjoys playing pranks on her professors and classmates and causing confusion about who is actually who. Her parents are divorced, but her father pays for her tuition. There is a rumor spreading across campus claiming that he is a porn star.'
+$npc_notes['A<<npctemp>>'] = 'The younger of the identical twins studying nursing at the university. She and Mia are inseparable and are seen almost everywhere together. Like her older sister, she enjoys playing pranks on her professors and classmates and causing confusion about who is actually who. Her parents are divorced, but her father pays for her tuition. There is a rumor spreading across campus claiming that he is a porn actor.'
 npc_dob['A<<npctemp>>'] = 19980325
 npc_gender['A<<npctemp>>'] = 1
 
@@ -477,7 +477,7 @@ $npc_firstname['A<<npctemp>>'] = 'Rostislav'
 $npc_nickname['A<<npctemp>>'] = 'Rostislav'
 $npc_lastname['A<<npctemp>>'] = 'Popov'
 $npc_usedname['A<<npctemp>>'] = 'Rostislav'
-$npc_notes['A<<npctemp>>'] = 'Radomir''s father, he is a fit attractive man in his early forties. He has a attitude that women only exist to provide sexual pleasure to men and that no man should ever be tied to a single woman. He believe it is natural for men to cheat on their wives or girlfriends and has passed his view down to his two sons. He works at one of the factories in the city.'
+$npc_notes['A<<npctemp>>'] = 'Radomir''s father. A fit and attractive man in his early forties, he believes that women only exist to provide sexual pleasure to men and that no man should ever be tied to a single woman. He believes it is natural for men to cheat on their wives or girlfriends and has passed his views down to his two sons. He works at one of the factories in the city.'
 npc_dob['A<<npctemp>>'] = 19741225
 npc_gender['A<<npctemp>>'] = 0
 
@@ -498,7 +498,7 @@ $npc_firstname['A<<npctemp>>'] = 'Radislav'
 $npc_nickname['A<<npctemp>>'] = 'slava'
 $npc_lastname['A<<npctemp>>'] = 'Popov'
 $npc_usedname['A<<npctemp>>'] = 'Radislav'
-$npc_notes['A<<npctemp>>'] = 'Radomir''s older brother, he is a fit attractive young man in his early to mid twenties. When he attended Pavlovsk school he was the captain of the football team and the top athlete, he won several awards. Afterwards he went to the University where he screwed around and flunked out, after that he moved back home and got a job in the same factor as his father.'
+$npc_notes['A<<npctemp>>'] = 'Radomir''s older brother, a fit and attractive young man in his early twenties. He was the captain of the Pavlovsk school''s football team and the top athlete, for which he won several awards. Afterwards, he went to the university, but screwed around and flunked out. He then moved back home and got a job in the same factory as his father.'
 npc_dob['A<<npctemp>>'] = 19940303
 npc_gender['A<<npctemp>>'] = 0
 
@@ -522,7 +522,7 @@ $npc_firstname['A<<npctemp>>'] = 'Maya'
 $npc_nickname['A<<npctemp>>'] = 'Maya'
 $npc_lastname['A<<npctemp>>'] = 'Semionova'
 $npc_usedname['A<<npctemp>>'] = 'Maya'
-$npc_notes['A<<npctemp>>'] = 'Maya is the daughter of Anitchka a freelance coryphée, she was encouraged to dance from a young age until she was nine when she started doing gymnastics. This changed when she was eleven when her mother became ill and she was asked to carry on the family tradition. Maya is a naturally gifted dancer and after six years is tipped to become one of Russia''s leading stars in the future.'
+$npc_notes['A<<npctemp>>'] = 'Maya is the daughter of Anitchka. A freelance coryphée, she was encouraged to dance from a young age until she was nine, when she started doing gymnastics. This changed when she was eleven, when her mother became ill and she was asked to carry on the family tradition. Maya is a naturally gifted dancer and after six years is tipped to become one of Russia''s leading stars in the future.'
 npc_dob['A<<npctemp>>'] = 19990502
 npc_gender['A<<npctemp>>'] = 1
 npc_bust['A<<npctemp>>'] = 14
@@ -543,8 +543,8 @@ gs 'npcstaticdefaults', 'skills', 'dance', 'sport'
 gs 'npcstaticdefaults', 'body', 'model'
 
 npctemp = 275
-!! Kima Agapova - The dance critic and fanatical to become a dancer, no matter the cost. Keeps a 'black book' of contacts and information. Arguably the best dancer in the school alongside Maya. She will try and gather information on Sveta's activities.
-!! will try and blackmail Sveta into either giving up if she learns if she's has dirty secrets such as prostitution, slut rep, etc or passing the information to Rudolph to destroy her career to remove her as competition.
+!! Kima Agapova - The dance critic and fanatical to become a dancer, no matter the cost. Keeps a 'black book' of contacts and information. Arguably the best dancer in the school alongside Maya. She will try and gather information on Sveta''s activities.
+!! will try and blackmail Sveta into either giving up if she learns she has dirty secrets such as prostitution, slut rep, etc or passing the information to Rudolph to destroy her career and remove her as competition.
 $npc_firstname['A<<npctemp>>'] = 'Kima'
 $npc_nickname['A<<npctemp>>'] = 'Kima'
 $npc_lastname['A<<npctemp>>'] = 'Agapova'
@@ -565,7 +565,7 @@ gs 'npcstaticdefaults', 'skills', 'dance', 'sport'
 gs 'npcstaticdefaults', 'body', 'model'
 
 npctemp = 277
-!! Galina Molchalina - Quiet and shy student, age 16. Highly secretive and doesn't engage with the class, she also has a nervous personality as if she's afraid. This comes from her family being marked as 'radicals' by the old KGB and under constant watch from FSB even to this day.
+!! Galina Molchalina - Quiet and shy student, age 16. Highly secretive and doesn't engage with the class, she also has a nervous personality as if she's afraid. This comes from her family being marked as 'radicals' by the old KGB and under constant watch from FSB, even to this day.
 $npc_firstname['A<<npctemp>>'] = 'Galina'
 $npc_nickname['A<<npctemp>>'] = 'Galina'
 $npc_lastname['A<<npctemp>>'] = 'Molchalina'
@@ -575,8 +575,8 @@ gs 'npcstaticdefaults', 'skills', 'dance', 'sport'
 gs 'npcstaticdefaults', 'body', 'model'
 
 npctemp = 278
-!! Taisiya Lebedeva - The eldest student, and an elegant beauty, Age 18. A quiet, but captivating beauty who has a enchanting charismatic presence that men can't keep their eyes off her leading to bitchy remarks from other girls.
-!! She''s oblivous to her beauty instead focusing on acting and dance. (side note: surname is one of the most common in St P.), she's got a strong religous personality.
+!! Taisiya Lebedeva - The eldest student, and an elegant beauty, Age 18. A quiet, but captivating beauty who has an enchanting charismatic presence, men can't keep their eyes off her, leading to bitchy remarks from other girls.
+!! She''s oblivous to her beauty, instead focusing on acting and dance. (side note: surname is one of the most common in St P.), she's got a strong religous personality.
 !! Character model: Malta Aurelie
 $npc_firstname['A<<npctemp>>'] = 'Taisiya'
 $npc_nickname['A<<npctemp>>'] = 'Taisiya'
@@ -587,7 +587,7 @@ gs 'npcstaticdefaults', 'skills', 'dance', 'sport'
 gs 'npcstaticdefaults', 'body', 'model'
 
 npctemp = 279
-!! Nikita Volkova - Bronya''s daughter. Age 16. Keep fit fanatic, and does tap, ballet, etc. As Bronya's daughter she's been given privileged access to the school, whilst not a great talent she's still one of the best dance students at the school but just not at ballet despite Bronya's hopes.
+!! Nikita Volkova - Bronya''s daughter. Age 16. Keep fit fanatic, and does tap, ballet, etc. As Bronya's daughter, she's been given privileged access to the school. While not a great talent, she's still one of the best dance students at the school. Just not at ballet, despite Bronya's hopes.
 $npc_firstname['A<<npctemp>>'] = 'Nikita'
 $npc_nickname['A<<npctemp>>'] = 'Volkova'
 $npc_lastname['A<<npctemp>>'] = 'Volkova'
@@ -601,7 +601,7 @@ $npc_firstname['A<<npctemp>>'] = 'Gasha'
 $npc_nickname['A<<npctemp>>'] = 'Gasha'
 $npc_lastname['A<<npctemp>>'] = 'Morozova'
 $npc_usedname['A<<npctemp>>'] = 'Gasha'
-$npc_notes['A<<npctemp>>'] = 'The youngest in the class at 15, close friend of Nikita as the grew up in the same village. Nikita and Galina are often seen in each others company in the local coffee shop and rarely seen alone leading to rumours. She''s a bit of a foodie, and love sweet things which conflicts with keeping in shape for her dance career.'
+$npc_notes['A<<npctemp>>'] = 'The youngest in the class at 15 and a close friend of Nikita as they grew up in the same village. Nikita and Galina are often seen in each other''s company in the local coffee shop and are rarely seen alone, leading to rumours. She''s a bit of a foodie and love sweets things, which conflicts with keeping in shape for her dance career.'
 npc_dob['A<<npctemp>>'] = 20000705
 npc_gender['A<<npctemp>>'] = 1
 npc_bust['A<<npctemp>>'] = 9
@@ -618,7 +618,7 @@ gs 'npcstaticdefaults', 'skills', 'dance', 'sport'
 gs 'npcstaticdefaults', 'body', 'model'
 
 npctemp = 281
-!! Calina and Ruza Sokolova - Twin dancers. Not interested in ballet, but took the course to further their education into becoming dancers. Age 17. They also professional models with a Moscow agency.
+!! Calina and Ruza Sokolova - Twin dancers. Not interested in ballet, but took the course to further their education into becoming dancers. Age 17. They are also professional models with a Moscow agency.
 !! Adel and Alina Fakhteeva twins?
 $npc_firstname['A<<npctemp>>'] = 'Calina'
 $npc_nickname['A<<npctemp>>'] = 'Callie'
@@ -643,7 +643,7 @@ $npc_nickname['A<<npctemp>>'] = 'Rudolf '
 $npc_lastname['A<<npctemp>>'] = 'Baryshnikov'
 $npc_usedname['A<<npctemp>>'] = 'Rudolf'
 npc_dob['A<<npctemp>>'] = 19820920
-$npc_notes['A<<npctemp>>'] = 'Rudolf is a charming and handsome man, he was on course to become one of Russia''s best ballet dancers until a stage accident cut short his career. Today he works at the dance school as a instructor, agent and a board member. Many rumours about his life have swirled around him over the years but none have been proven.'
+$npc_notes['A<<npctemp>>'] = 'Rudolf is a charming and handsome man who was on course to become one of Russia''s best ballet dancers until a stage accident cut short his career. He now works at the dance school as an instructor, agent and a board member. Many rumours about his life have swirled around him over the years, but none have ever been proven.'
 npc_gender['A<<npctemp>>'] = 0
 gs 'npcstaticdefaults', 'defaults'
 $npc_thdick['A<<npctemp>>'] = 'slim'
@@ -662,6 +662,7 @@ $npc_nickname['A<<npctemp>>'] = ''
 $npc_lastname['A<<npctemp>>'] = 'Ananiashvili'
 $npc_img_path['A<<npctemp>>'] = 'images/characters/ballet'
 gs 'npcstaticdefaults', 'defaults'
+
 !! class teacher/pianist: Sofia Solovyova
 npctemp = 285
 $npc_firstname['A<<npctemp>>'] = 'Sofia'
@@ -669,7 +670,8 @@ $npc_nickname['A<<npctemp>>'] = 'Sofia'
 $npc_lastname['A<<npctemp>>'] = 'Solovyova'
 $npc_img_path['A<<npctemp>>'] = 'images/characters/ballet'
 gs 'npcstaticdefaults', 'defaults'
-!! Residential Warden: Bronya Volkova and former violinist, strict but fair has two daughters with Nikita being the youngest training to be a ballet dancer and her eldest in Germany training to be a surgeon.
+
+!! Residential Warden: Bronya Volkova and former violinist. Strict but fair. Has two daughters, with Nikita, the youngest, training to be a ballet dancer and her eldest in Germany training to be a surgeon.
 npctemp = 286
 $npc_firstname['A<<npctemp>>'] = 'Bronya'
 $npc_nickname['A<<npctemp>>'] = 'Bronya '
@@ -678,6 +680,7 @@ $npc_usedname['A<<npctemp>>'] = 'Bronya'
 gs 'npcstaticdefaults', 'defaults'
 $npc_img_path['A<<npctemp>>'] = 'images/characters/ballet'
 gs 'npcstaticdefaults', 'defaults'
+
 !! reserved for future content
 !! NPC temp: 287 - Physio - Pelageya Makarova
 
@@ -686,6 +689,9 @@ gs 'npcstaticdefaults', 'defaults'
 !! NPC temp: 288 Staff Physio -  Syuzanna Zakharova / Klavdii Frolov (Klavdii is a pun)
 !! NPC temp: 289 Mistress of Ballet - Zarya Popova
 
+
+
 !! {Keep this at the end of file of the npcstatics.}
 aarraynumber = npctemp
+
 --- npcstatic6 ---------------------------------

+ 1 - 2
locations/pirsingsalon.qsrc

@@ -1817,8 +1817,7 @@ if $ARGS[0] = 'tattoo_wrist':
 end
 
 if $ARGS[0] = 'tattoo_wrist2':
-	'<center><img src="<<func(''tattoo_management'', ''			*p '<a href="exec: gt ''pirsingsalon'', ''tattoo_wrist2'', <<ps_i>>"><img height="250" src="<<func(''tattoo_management'', ''wrist_image'', ps_i)>>"></a>'
-'', ARGS[1])>>"></center>'
+	'<center><img src="<<func(''tattoo_management'', ''wrist_image'', ARGS[1])>>"></center>'
 
 	if max(money, karta) < 7000:
 		'You cannot afford this tattoo.'

+ 9 - 9
locations/pornfilm.qsrc

@@ -42,13 +42,13 @@ if $ARGS[0] = 'pornactor':
 			if num < pfactor:
 				num2 = pfactor
 				:actorloop2
-					if $pactor[num] = $pactor[num2]:jump 'actorloop'
+					if $pactor[num] = $pactor[num2]: jump 'actorloop'
 					num2 -= 1
-				if num2 > num:jump 'actorloop2'
+				if num2 > num: jump 'actorloop2'
 			end
-			if aksex[akrand] = 0:aksex[akrand] = 1 & guy += 1
+			if aksex[akrand] = 0: aksex[akrand] = 1 & guy += 1
 			num -= 1
-		if num > 0:jump 'actorloop'
+		if num > 0: jump 'actorloop'
 	end
 end
 
@@ -61,7 +61,7 @@ if $ARGS[0] = 'pornactress':
 				$pactress[num] = 'Krystal'
 				$pactressID[num] = 'A207'
 			elseif akrand = 2:
-				$pactress[num] = 'Ellie Knight'
+				$pactress[num] = 'Ash Lee'
 				$pactressID[num] = 'A234'
 			elseif akrand = 3:
 				$pactress[num] = 'Juliana Slavenka'
@@ -79,13 +79,13 @@ if $ARGS[0] = 'pornactress':
 			if num < pfactor:
 				num2 = pfactor
 				:actressloop2
-					if $pactress[num] = $pactress[num2]:jump 'actressloop'
+					if $pactress[num] = $pactress[num2]: jump 'actressloop'
 					num2 -= 1
-				if num2 > num:jump 'actressloop2'
+				if num2 > num: jump 'actressloop2'
 			end
-			if aksex[akrand] = 0:aksex[akrand] = 1 & girl += 1
+			if aksex[akrand] = 0: aksex[akrand] = 1 & girl += 1
 			num -= 1
-		if num > 0:jump 'actressloop'
+		if num > 0: jump 'actressloop'
 	end
 end
 

+ 7 - 2
locations/pushkin_ballet_class.qsrc

@@ -34,8 +34,12 @@ if $ARGS[0] = 'start':
 
 	!! Random trivia - Terpsichore is one of the nine Greecian muses. Her sphere was dance, rhythm and choral music.
 
-	if ballet_day = 6 and balletqw['school'] ! 1:
+	if (balletqw['daystart'] + 7 = daystart) and hour = 7:
 		gt $loc, 'assessment'
+	elseif ( daystart >= balletqw['daystart'] + 8 ) or (balletqw['daystart'] + 7 = daystart and hour > 7):
+		mod_grade_score['class'] -= 500
+		'You were late or did not attend the exam. You have failed the course.'
+		act 'Return home' : gt 'pav_commcenter'
 	elseif ballet_day = 6 and balletqw['school'] = 1:
 		gs 'stat'
 		gs 'core_library', 'stage_title'
@@ -314,7 +318,8 @@ if $ARGS[0] = 'shower':
 	end
 end
 if $ARGS[0] = 'grade_check':
-	$popup_advise = '<center><h3>You critically look at your appearance according to the schools assessment guidelines:</h3></center>'
+	$popup_advise = '<center><h3>Appearance</h3></center>'
+	$popup_advise += 'You critically look at your appearance according to the schools assessment guidelines:'
 	$popup_advise += '<br><br>'
 	if pcs_makeup > 1:
 		$popup_advise += '<font color = "green">✓</font> Your make up is of an acceptable standard.</font>'

+ 1 - 0
locations/pushkin_ballet_evt.qsrc

@@ -337,6 +337,7 @@ end
 
 if $ARGS[0] = 'intro_274':
 	*clr & cla
+	mayaqw['path'] = 1
 	'<center><a><img <<$set_imgh>> src="<<$npc_img_path[''A274'']>>/274-1.jpg"></center>'
 	'You walk over to a tall willowly blonde girl, "Hi I''m <<$pcs_nickname>>". The girl gives you a warm smile, "I''m <<$npc_firstname[''A274'']>> pleased to meet you. Where you from?" ''Pavlosk'' you reply, ''Yourself?'''
 	'"I live Pushkin now but from Moscow originally.", <<$npc_firstname[''A274'']>> replles before another girl jumps in taking her attention.'

+ 2 - 1
locations/pushkin_ballet_init.qsrc

@@ -25,6 +25,7 @@
 !! balletqw[performances] - How many shows perfomed
 !! mayaqw[grave] - Did you attend Anitchka's grave with Maya, 3 means you talked to Maya, 4 means you were empathic. Has impact later on Maya''s actions towards the player.
 !! mayaqw[trust] - How much Maya trusts you and works in conjunction with npc_rel
+!! mayaqw[path] - progress tracker for maya quests
 !! Rudolph quest is broken into two variables the main tracker being rudolphqw[stage] and rudolphqw[corruption], the latter reflects his slow insidious undermining of Sveta''s confidence and the former is how
 !! much she has submitted to his authority and demands. Corruption opens dialogue options.
 !!
@@ -220,7 +221,7 @@ if $ARGS[0] = 'cleanup_var':
 	killvar 'mod_grade_uniform'
 	killvar 'mod_grade_health'
 	killvar 'mod_class_debug'
-
+	gs 'shortgs', 'remove_array_element', 'balletqw', 'daystart'
 	gs 'shortgs', 'remove_array_element', 'ballet_mod', 'letter'
 	gs 'shortgs', 'remove_array_element', 'ballet_mod', 'res_mg'
 end

+ 9 - 3
locations/pushkin_ballet_res.qsrc

@@ -11,7 +11,7 @@
 !!
 !! Variables
 !!
-!! ballet_first_visit - used to set first night
+!! balletqw[daystart] - used to set first night
 !! ballet_day - Sets which day of the course you are on.
 
 $default_img_path = 'locations/pushkin/'
@@ -48,10 +48,10 @@ if $ARGS[0] = 'bedroom':
 	gs 'stat'
 	gs 'core_library', 'stage_title'
 
-	if ballet_first_visit = 0:
+	if balletqw['daystart'] = 0:
 		gs 'homes_properties', 'set_home', 'pushkin_ballet_dorm'
 
-		ballet_first_visit = 1
+		balletqw['daystart'] = daystart
 		if week ! 7 : ballet_day = week
 
 		'You look around your room that will be the bedroom for the next week, and a small comfortable bed sits in the corner. You have a desk you can study on. In the corner, there''s a full-size <a href="exec:gt ''wardrobe'', ''start''">wardrobe</a> with a mirror on one of the doors.'
@@ -82,6 +82,8 @@ if $ARGS[0] = 'bedroom':
 			act 'Answer the knock' : gs 'npc_274_init','grave'
 		elseif ballet_day = 3 and hour > 19 and mayaqw['grave'] = 1:
 			act 'Another knock': gt 'npc_274_init', 'post_grave'
+		else
+			mayaqw['grave'] = -1
 		end
 		!! Default actions
 		gs 'core_library', 'bedroom'
@@ -309,9 +311,13 @@ if $ARGS[0] = 'class_schedule':
 	'1600 - 1700: Ballet and musical theory.'
 	*nl
 	'Saturday:'
+	'0730 - Depart residence.'
 	'0800 - 1200: Graded assessment.'
 	*nl
+	'Transportation will be provided after the assessment and you will be informed of your results by letter in two weeks.'
+	*nl
 	'Rules:'
+	*nl
 	'Whilst attending classes students are expected dressed in sports clothing, perferably a leotard.'
 	'You must also set your hair in a braid or a bun, no other styles are acceptable.'
 	'Make up must be worn at all times, and you must be clean and presentable during classes. You will have access to showers during the day.'

+ 38 - 11
locations/quest_data_a274.qsrc

@@ -1,14 +1,19 @@
 # quest_data_a274
-
 !! NPC 274 Maya Semionova
 
 if $ARGS[0] = 'init':
+    $loc_id = 'quest_data_a274'
     !! init all vars and data
 
     if ballet['debug'] = 1:  debug['code']  = 1
-
+    if qstage ! 0:
+		gs $loc_id, 'quest_body', 'stage_<<qstage>>'
+	else
+		gt $loc_id, 'debug'
+	end
 end
-if ARGS[0] = '':
+if $ARGS[0] = '':
+	gt $loc_id, 'debug'
 end
 if $ARGS[0] = 'quest_body':
     !! create quest body and navigation as required - mandatory fields:
@@ -20,28 +25,50 @@ if $ARGS[0] = 'quest_body':
 
     !! Stage 1
 
-    if $ARGS[1] = 'stage1':
+    if $ARGS[1] = 'stage_1':
     !! first stage, so set to null to ensure nav works.
         $npc_quest['q_back'] = 'null'
-        $npc_quest['q_next'] = 'stage2'
+        if mayaqw['path'] >= 1:
+            $npc_quest['q_next'] = 'stage_2'
+        else
+            $npc_quest['q_next'] = 'null'
+        end
+        $npc_quest['hints'] = 'Attend the Pushken Ballet School and interact with the students.'
     !! Quest body text:
-        $npc_['quest_body'] = 'Build Maya''s trust: Meet Maya at the Residential Dance School in Pushkin.'
+        $npc_quest['body'] = 'Build Maya''s trust: Meet Maya at the Residential Dance School in Pushkin.'
     end
 
     !! Stage 2
-    if $ARGS[1] = 'stage2':
-        !! first stage, so set to null to ensure nav works.
-            $npc_quest['q_back'] = 'stage1'
+    if $ARGS[1] = 'stage_2':
+		$npc_quest['q_back'] = 'stage_1'
+        if mayaqw['path'] >= 3:
+            $npc_quest['q_next'] = 'stage_3'
+        else
             $npc_quest['q_next'] = 'null'
-        !! Quest body text:
-            $npc_['quest_body'] = 'Build Maya''s trust: Continue to meet and talk to Maya.'
         end
 
+		$npc_quest['q_next'] = 'null'
+        $npc_quest['hints'] = 'Accept Maya''s invitation.'
+        if mayaqw['grave'] = 0:
+            $npc_quest['body'] = 'Build Maya''s trust: Continue to meet and talk to Maya.'
+        elseif mayaqw['grave'] = -1:
+            $npc_quest['body'] = 'You spent the evening dedicated to studying ballet and ignored Maya''s visit to your room.'
+        elseif mayaqw['grave'] = 1:
+            $npc_quest['body'] = 'You ignored Maya''s first knock when she came to visit.'
+        elseif mayaqw['grave'] = 3:
+            $npc_quest['body'] =  'You invited Maya into your room and had a brief heartfelt conversation about her past.'
+        elseif mayaqw['grave'] = 4:
+            $npc_quest['body'] = 'You went to graveyard and supported Maya in her grief, and had a hearftelt conversation with her afterwards in your room.'
+        end
+    end
+
 
     !! Stage 3
 
+
 end
 if $ARGS[0] = 'debug':
     !! creata debug data sheet of all associated variables to be displayed in a pop up
+    'Event init failed, $ARGS not set.'
 end
 --- quest_data_a274 ---------------------------------

+ 8 - 8
locations/uni_admin.qsrc

@@ -251,25 +251,25 @@ if $ARGS[0] = 'enrollment_semester':
 					gs 'grades', 'createclass', 'uni_nursing_semester_2', 'patient care 102', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_2', 'anatomy and physiology 102', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_2', 'examination and treatment 102', 1, 2, 'no', 'no', 1, 12
-					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'patient care 102', (class['uni_nursing_semester_1_patient_care 101_grade']/3+10)
-					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'anatomy and physiology 102', (class['uni_nursing_semester_1_anatomy_and_physiology 101_grade']/3+10)
-					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'examination and treatment 102', (class['uni_nursing_semester_1_examination_and_treatment 101_grade']/3+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'patient care 102', (class['uni_nursing_semester_1_patient care 101_grade']/3+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'anatomy and physiology 102', (class['uni_nursing_semester_1_anatomy and physiology 101_grade']/3+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_2', 'examination and treatment 102', (class['uni_nursing_semester_1_examination and treatment 101_grade']/3+10)
 				elseif university['enrolled_in_semester'] = 3:
 					!!This creates the classes for the third semester of the nursing program to be used by the grade system, and gives the player a starting grade value (which is a failing grade, the player has to study if they want to pass)
 					gs 'grades', 'createclass', 'uni_nursing_semester_3', 'patient care 201', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_3', 'anatomy and physiology 201', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_3', 'dosages and pharmaceuticals 101', 1, 2, 'no', 'no', 1, 12
-					gs 'grades', 'grade_award', 'uni_nursing_semester_3', 'patient care 201', ((class['uni_nursing_semester_1_patient_care 101_grade'] + class['uni_nursing_semester_2_patient_care 102_grade'])/6+10)
-					gs 'grades', 'grade_award', 'uni_nursing_semester_3', 'anatomy and physiology 201', ((class['uni_nursing_semester_1_anatomy_and_physiology 101_grade'] + class['uni_nursing_semester_2_anatomy_and_physiology 102_grade'])/6+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_3', 'patient care 201', ((class['uni_nursing_semester_1_patient care 101_grade'] + class['uni_nursing_semester_2_patient care 102_grade'])/6+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_3', 'anatomy and physiology 201', ((class['uni_nursing_semester_1_anatomy and physiology 101_grade'] + class['uni_nursing_semester_2_anatomy and physiology 102_grade'])/6+10)
 					gs 'grades', 'grade_award', 'uni_nursing_semester_3', 'dosages and pharmaceuticals 101', 35
 				elseif university['enrolled_in_semester'] = 4:
 					!!This creates the classes for the fourth semester of the nursing program to be used by the grade system, and gives the player a starting grade value (which is a failing grade, the player has to study if they want to pass)
 					gs 'grades', 'createclass', 'uni_nursing_semester_4', 'patient care 202', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_4', 'anatomy and physiology 202', 4, 2, 'no', 'no', 1, 12
 					gs 'grades', 'createclass', 'uni_nursing_semester_4', 'dosages and pharmaceuticals 102', 1, 2, 'no', 'no', 1, 12
-					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'patient care 202', ((class['uni_nursing_semester_1_patient_care 101_grade'] + class['uni_nursing_semester_2_patient_care 102_grade'] + class['uni_nursing_semester_3_patient_care 201_grade'])/9+10)
-					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'anatomy and physiology 202', ((class['uni_nursing_semester_1_anatomy_and_physiology 101_grade'] + class['uni_nursing_semester_2_anatomy_and_physiology 102_grade'] + class['uni_nursing_semester_3_anatomy_and_physiology 201_grade'])/9+10)
-					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'dosages and pharmaceuticals 102', (class['uni_nursing_semester_3_dosages_and_pharmaceuticals 101_grade']/3+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'patient care 202', ((class['uni_nursing_semester_1_patient care 101_grade'] + class['uni_nursing_semester_2_patient care 102_grade'] + class['uni_nursing_semester_3_patient care 201_grade'])/9+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'anatomy and physiology 202', ((class['uni_nursing_semester_1_anatomy and physiology 101_grade'] + class['uni_nursing_semester_2_anatomy and physiology 102_grade'] + class['uni_nursing_semester_3_anatomy and physiology 201_grade'])/9+10)
+					gs 'grades', 'grade_award', 'uni_nursing_semester_4', 'dosages and pharmaceuticals 102', (class['uni_nursing_semester_3_dosages and pharmaceuticals 101_grade']/3+10)
 				end
 				cla
 				'You tell her you would like to continue pursuing a nursing degree. She smiles and nods, then finishes filling out some more paperwork about the courses you can expect to take.'

+ 8 - 3
locations/wardrobe.qsrc

@@ -229,18 +229,19 @@ $default_clothing_line = {
 	!! ARGS 2 - clothing index
 
 	gs 'themes', 'clothing'
-	gs 'clothing_attributes', $defclothingtype[default_entry], defclothingnumber[default_entry]
 
 	$RESULT = '<TR bgcolor='+$temp_bcolor+'>'
 
 	$RESULT +='<TD><b><<$def_clothing_name[default_entry]>></b></TD>'
 
+	gs 'clothing_attributes', $defclothingtype[default_entry], defclothingnumber[default_entry]
 	if defclothingnumber[default_entry] = 0:
 		$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 	else
 		$RESULT +='<TD><img width="100" src="<<FUNC(''$clothing_image'', $defclothingtype[default_entry], defclothingnumber[default_entry])>>"></TD>'
 	end
 	if defunderwear[default_entry] = 2:
+		gs 'underwear_attributes', $defbodysuittype[default_entry]+'_bodysuits', defbodysuitnumber[default_entry]
 		if defbodysuitnumber[default_entry] = 0:
 			$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 		else
@@ -248,22 +249,26 @@ $default_clothing_line = {
 		end
 		$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 	else
+		gs 'underwear_attributes', $defbratype[default_entry]+'_bras', defbranumber[default_entry]
 		if defbranumber[default_entry] = 0:
 			$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 		else
 			$RESULT +='<TD><img width="100" src="<<FUNC(''$bra_image'', $defbratype[default_entry], defbranumber[default_entry])>>"></TD>'
 		end
+		gs 'underwear_attributes', $defpantytype[default_entry]+'_panties', defpantynumber[default_entry]
 		if defpantynumber[default_entry] = 0:
 			$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 		else
 			$RESULT +='<TD><img width="100" src="<<FUNC(''$panty_image'', $defpantytype[default_entry], defpantynumber[default_entry])>>"></TD>'
 		end
 	end
+	gs 'shoe_attributes', $defshoetype[default_entry], defshoenumber[default_entry]
 	if defshoenumber[default_entry] = 0:
 		$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 	else
 		$RESULT +='<TD><img width="100" src="<<FUNC(''$shoe_image'', $defshoetype[default_entry], defshoenumber[default_entry])>>"></TD>'
 	end
+	gs 'coat_attributes', $defcoattype[default_entry], defcoatnumber[default_entry]
 	if defcoatnumber[default_entry] = 0:
 		$RESULT +='<TD><img width="100" src="images/pc/items/blank.jpg"></TD>'
 	else
@@ -594,7 +599,7 @@ if $ARGS[0] = 'default_entry_wear':
 	end
 
 	!! default school girl uniform is always allowed to be worn if still in school
-	if mid($start_type,1,2) = 'sg' and SchoolAtestat = 0 and SchoolBlock = 0 and $temp1 = 'gm_school' and temp2 = 6:
+	if $start_type['loc'] = 'sg' and SchoolAtestat = 0 and SchoolBlock = 0 and $temp1 = 'gm_school' and temp2 = 6:
 		cla & *clr
 		'<center><video autoplay loop src="images/pc/activities/misc/dress_1.mp4"></video></center>'
 		'Your put on your <<$def_clothing_name[default_entry]>> outfit without any problems.'
@@ -649,7 +654,7 @@ if $ARGS[0] = 'default_entry_wear':
 			act 'Return': gt 'wardrobe', $wloc
 		end
 	!! not exercise clothing, and not loose fitting
-	elseif (CloStyle2 ! 6 and CloStyle ! 5) or $temp1 ! 'nude':
+	elseif CloStyle2 ! 6 and CloStyle ! 5 and $temp1 ! 'nude':
 		!! check for if the hipsize is too far from your hipsize
 		dynamic 'RESULT = <<$temp1>>_b[<<temp2>>]'
 		if RESULT < pcs_hips - 8 or RESULT > pcs_hips + 8:

+ 10 - 2
qsrc2tw/package-lock.json

@@ -5,6 +5,7 @@
   "packages": {
     "": {
       "dependencies": {
+        "@types/jqueryui": "^1.12.23",
         "gridstack": "^10.3.1"
       },
       "devDependencies": {
@@ -35,17 +36,24 @@
       "version": "3.5.30",
       "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz",
       "integrity": "sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@types/sizzle": "*"
       }
     },
+    "node_modules/@types/jqueryui": {
+      "version": "1.12.23",
+      "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.23.tgz",
+      "integrity": "sha512-pm1yVNVI29B9IGw41anCEzA5eR2r1pYc7flqD471ZT7B0yUXIY7YNe/zq7LGpihIGXNzWyG+Q4YQSzv2AF3fNA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/jquery": "*"
+      }
+    },
     "node_modules/@types/sizzle": {
       "version": "2.3.8",
       "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
       "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/@types/twine-sugarcube": {

+ 1 - 0
qsrc2tw/package.json

@@ -7,6 +7,7 @@
   },
   "types": "twine-code/interfaces.d.ts",
   "dependencies": {
+    "@types/jqueryui": "^1.12.23",
     "gridstack": "^10.3.1"
   }
 }

+ 4 - 3
qsrc2tw/tools/QSRC2TW/index.js

@@ -9,7 +9,7 @@ import os from 'node:os';
 
 import { execSync } from 'node:child_process';
 
-const VERSION = 6;
+const VERSION = 8;
 const generatedFilesPrefix = '-generated';
 const resourcesFilesPrefix = '+resources';
 
@@ -17,7 +17,7 @@ const program = new Command();
 program
   .name('QSP TO Sugarcube')
   .description('CLI to Convert Quest Soft sourcecode to Twine Sugarcube')
-  .version('0.0.6')
+  .version('0.0.8')
   .option('-in, --input-file-path <path>','the path where the qsrc-files are')
   .option('-out, --output-file-path <path>','the path where the tw-files go')
   .option('-f, --single-file <path>','only converts the specified file')
@@ -126,7 +126,8 @@ fs.cpSync("./resources", resourcesPath, {recursive: true});
 
 
 const executionTime =  (new Date()).getTime() - startTime;
-console.log('ENDED CONVERSION'.padEnd(30,'.')+ ' '+executionTime+' ms'+` (${filePaths.length-failedFiles.length} of ${filePaths.length} successful)`);
+const executionTimeString = `${Math.floor(executionTime/3600000).toString().padStart(2,'0')}:${Math.floor(executionTime % 3600000 / 60000).toString().padStart(2,'0')}:${Math.floor(executionTime % 60000 /1000).toString().padStart(2,'0')}.${(executionTime % 1000).toString().padStart(4,'0')}`;
+console.log('ENDED CONVERSION'.padEnd(30,'.')+ ' '+executionTimeString+` (${filePaths.length-failedFiles.length} of ${filePaths.length} successful)`);
 
 //#region Versioning File
     const pathOfVersioningFile = path.join(outPath,generatedFilesPrefix,'version.js');

+ 5 - 0
qsrc2tw/tools/QSRC2TW/resources/QSP-functions/strpos.js

@@ -0,0 +1,5 @@
+setup.qsp_strpos = (s, search, ...additionalArgs) => {
+    if(additionalArgs[0])
+        throw new Error("setup.qsp_strpos with more than 2 arguments is not implemented.");
+    return s.indexOf(search)+1;
+}

+ 1 - 1
qsrc2tw/tools/QSRC2TW/resources/QSP-macros/GT.js

@@ -88,7 +88,7 @@ Macro.add('gt', {
 	skipArgs : false,
 	handler  : function () {
 		try{
-			setup.gt(...this.args);
+			setup.qsp_gt(...this.args);
 		}
 		catch (ex) {
 			return this.error('ERROR in gt-widget: ' + ex.message);

Plik diff jest za duży
+ 1 - 0
qsrc2tw/tools/QSRC2TW/resources/resources/Topbar.css


+ 8 - 0
qsrc2tw/tools/QSRC2TW/resources/resources/Topbar.tw

@@ -42,4 +42,12 @@
 			<<run UI.restart();>>
 		<</button>>
 	<</id>>
+
+	<<id 'buttonEditor'>>
+		<<button 'E'>>
+			<<set _returnArgs = $args ?? [QSP.$ARGS[0]]>>
+			<<set $editor={"passage":State.passage, "returnPassage":State.passage, "returnArgs": _returnArgs}>>
+			<<goto 'editor'>>
+		<</button>>
+	<</id>>
 </div>

+ 4 - 2
qsrc2tw/tools/QSRC2TW/src/visitor/QsrcVisitor.js

@@ -269,9 +269,11 @@ export default class QsrcVisitor extends qsrcParserVisitor{
     }
 
     visitNumberLiteralWithOptionalSign(ctx){
+        const numberText = ctx.NumberLiteral().getText();
+        const number = Number(numberText); //Catch the edge cases where a number is prefixed with 0
         if(ctx.MINUS())
-            return `-${ctx.NumberLiteral().getText()}`;
-        return ctx.NumberLiteral().getText();
+            return `-${number}`;
+        return `${number}`;
     }
 
 

+ 81 - 0
qsrc2tw/tools/QSRC2TW/src/wardrobeItems.js

@@ -0,0 +1,81 @@
+//Don't forget to add the d-flag to your regex! It's needed for the use of indices.
+function splitByRegex(text,regex, callback){
+	let result = [];
+
+	let regexResult;
+	let previousEndIndex;
+	let previousRegexResult;
+
+	while(regexResult = regex.exec(text))
+	{
+        let thisEndIndex = regexResult.indices[0][1];
+        let thisStartIndex = regexResult.indices[0][0];
+        if(previousEndIndex){
+            const previousCodeSegment = text.substring(previousEndIndex,thisStartIndex);
+			result.push(callback(previousRegexResult,previousCodeSegment));
+
+        }
+
+        previousRegexResult = regexResult;
+        previousEndIndex = thisEndIndex;
+	}
+
+
+	let thisStartIndex = text.length;
+	const previousCodeSegment = text.substring(previousEndIndex,thisStartIndex);
+	result.push(callback(previousRegexResult,previousCodeSegment));
+
+	return result;
+}
+
+function stripPrefixFromObjectKeys(obj, prefix){
+	return Object.fromEntries(Object.entries(obj).map(([key,val]) => {
+		if(key.startsWith(prefix) && key.length > prefix.length)
+			return [key.substring(prefix.length),val];
+		return [key,val];
+	}));
+}
+
+export default function wardrobeItems(code,options){
+	let firstLine = code.split("\n")[0];
+	let twCode = firstLine.replace("#","::")+`\n`;
+
+	const itemIdPrefix = firstLine.trim().replace("# $attributes_","");
+
+	let tsCode = "setup.wardrobeStatic ??= {};\n";
+
+	const propertyRegex = /^\s*(\w+)\s*=\s*(\d+)\s*$/gm;
+	const stringPropertyRegex = /^\s*\$(\w+)\s*=\s*('|")(.*?)\2\s*$/gm;
+
+	const itemData = splitByRegex(code, /(?:else)?if\s+args\[1\]\s*=\s*(\d+):/gmid,
+		(regexResult,code) => {
+			const itemId = `${itemIdPrefix}_${regexResult[1]}`;
+
+			let properties = {};
+			let propertyRegexResult;
+			while(propertyRegexResult = propertyRegex.exec(code))
+				properties[propertyRegexResult[1]] = Number(propertyRegexResult[2]);
+			while(propertyRegexResult = stringPropertyRegex.exec(code))
+				properties[propertyRegexResult[1]] = propertyRegexResult[3];
+
+			if(properties['CloQuality'])
+				properties = Object.assign({type:'clothes'},stripPrefixFromObjectKeys(properties,'Clo'));
+			else if(properties['ShoQuality'])
+				properties = Object.assign({type:'shoes'},stripPrefixFromObjectKeys(properties,'Sho'));
+			else if(properties['BraQuality'])
+				properties = Object.assign({type:'bra'},stripPrefixFromObjectKeys(properties,'Bra'));
+			else if(properties['PanQuality'])
+				properties = Object.assign({type:'bra'},stripPrefixFromObjectKeys(properties,'Pan'));
+			else if(properties['CoatQuality'])
+				properties = Object.assign({type:'coat'},stripPrefixFromObjectKeys(properties,'Coat'));
+
+			if(options.shop)
+				properties.shop = options.shop;
+
+			return `setup.wardrobeStatic['${itemId}'] = ${JSON.stringify(properties)}\n`
+
+		});
+	tsCode += itemData.join("");
+
+	return [twCode,tsCode];
+}

+ 22 - 9
qsrc2tw/tools/QSRC2TW/task_processor.js

@@ -7,6 +7,7 @@ import path from "path";
 import defaultProcess from "./src/defaultProcess.js";
 import npcInit from "./src/npcInit.js";
 import skillDefinitions from "./src/skillDefinitions.js";
+import wardrobeItems from "./src/wardrobeItems.js";
 
 
 
@@ -64,20 +65,32 @@ function convertFile(task){
 		//#endregion
 
 		var convertMode = "default";
-
-		if(qsp2twOptions.startsWith("!! QSRC2TW_module")){
+		var convertModeOptions = {};
+		/*if(qsp2twOptions.startsWith("!! QSRC2TW_module")){
 			convertMode = qsp2twOptions.trim().split(" ").toReversed()[0];
+		}*/
+		const modeLookupRegex = /\s*!!\s*QSRC2TW_module\s+(\w+)(\s+{[^}]+})?/;
+		let modeLookupResult;
+		try{
+			if(modeLookupResult = modeLookupRegex.exec(qsp2twOptions)){
+				convertMode = modeLookupResult[1];
+				if(modeLookupResult[2])
+					convertModeOptions = JSON.parse(modeLookupResult[2]);
+			}
+		}
+		catch(e){
+			console.log(e.toString());
 		}
-
 
 		/**
 		 * Return value is Array [TwineCode, TSCode]. TwineCode must not be null.
 		 */
-		var convertFunction = (code)=>[null,null];
+		var convertFunction = (code,options)=>[null,null];
 		switch (convertMode) {
-			case "default": convertFunction = (code) => [defaultProcess(code),null]; break;
-			case "npcInit": convertFunction = (code) => npcInit(code); break;
-			case "stat_sklattrib_lvlset": convertFunction = (code) => skillDefinitions(code); break;
+			case "default": convertFunction = (code,options) => [defaultProcess(code),null]; break;
+			case "npcInit": convertFunction = (code,options) => npcInit(code); break;
+			case "stat_sklattrib_lvlset": convertFunction = (code,options) => skillDefinitions(code); break;
+			case "wardrobeItems": convertFunction = (code,options) => wardrobeItems(code,options); break;
 			default:
 				console.warn("Unreckognized Convert Mode");
 				break;
@@ -93,7 +106,7 @@ function convertFile(task){
 			if(!options.verboseErrors)
 				console = {log:(...args)=>{}, debug: (...args)=>{},warn:(...args)=>{}, error: (...args)=>{}};
 			try{
-				[twineCodeRaw,tsCodeRaw] = convertFunction(data);
+				[twineCodeRaw,tsCodeRaw] = convertFunction(data,convertModeOptions);
 			}
 			catch(e){
 				throw e;
@@ -102,7 +115,7 @@ function convertFile(task){
 				console = defaultConsole;
 			}
 			if(!twineCodeRaw){
-				console.error("Twine Code must be generated by every converMode");
+				console.error("Twine Code must be generated by every convertMode");
 				return [2,"Invalid convertFunction"];
 			}else{
 				twineCode = twineCodeRaw.split('\n')

Plik diff jest za duży
+ 0 - 0
qsrc2tw/tools/tweeGo/storyFormats/sugarcube-2/format.js


+ 81 - 0
qsrc2tw/twine-code/editor/Editor.css

@@ -0,0 +1,81 @@
+#passages:has(> #passage-editor){
+	grid-column: 1 / -1;
+	grid-row: 2 / -1;
+	z-index: 10;
+	padding: 0;
+	position: relative;
+}
+
+#passage-editor{
+	position: absolute;
+	display: grid;
+	grid-template-rows: auto 1fr;
+	grid-template-columns: 1fr repeat(3, min-content);
+	width: 100%;
+	height: 100%;
+}
+
+#passage-editor #commonTasks div{
+	margin-bottom: 1em;
+}
+
+#passage-editor #commonTasks div:hover {
+	background: #ccc;
+}
+
+#editorToolbar {
+	grid-column: 1 / -1;
+}
+
+
+.collapsable>h2{
+	cursor: pointer;
+}
+
+.collapsable h3 {
+	margin: 1em 0 0 0;
+	display: inline-block;
+	min-width: 6vw;
+}
+
+.collapsable{
+	--transitionSpeed: 0.3s;
+	transition: var(--transitionSpeed);
+	width: 30vw;
+	width: calc(30vw - 1em);
+	padding: 0 1em;
+	overflow: auto;
+}
+
+.collapsable.collapsed{
+	width: 2rem;
+	padding: 0;
+}
+
+.collapsable.collapsed>*{
+	display: none;
+}
+
+.collapsable.collapsed > h2:first-of-type {
+	font-size: 1em;
+	writing-mode: vertical-rl;
+	margin: 0;
+	transition: var(--transitionSpeed);
+	display: block;
+}
+
+.diff{
+	font-size: 0.7em;
+}
+
+.diff p{
+	margin: 0;
+}
+
+.diff p.addition{
+	color: rgb(0, 160, 0);
+}
+
+.diff p.substraction {
+	color: rgb(160,0, 0);
+}

+ 15 - 0
qsrc2tw/twine-code/editor/Editor.js

@@ -0,0 +1,15 @@
+
+setup.startEditor = (domId, text) =>{
+	setup.externalCodePromise('ace').then(()=>{
+		const editor = ace.edit(domId);
+		editor.setOption("showInvisibles", true);
+		editor.setTheme("ace/theme/chrome");
+		editor.session.setMode("ace/mode/html");
+		editor.session.setUseWorker(false);
+		editor.setValue(text);
+
+		setup.editor = editor;
+	});
+
+
+}

+ 121 - 0
qsrc2tw/twine-code/editor/Editor.tw

@@ -0,0 +1,121 @@
+:: editor
+
+<<set _changedFiles = JSON.parse(localStorage.getItem("SweetCube.Modifications") ?? '{}')>>
+
+<div id="editorToolbar">
+	<<=$editor.passage>>
+
+	<<button 'Save'>>
+		<<run setup.editorSave($editor.passage,setup.editor.getValue())>>
+	<</button>>
+	<<button 'Return'>>
+		<<gt $editor.returnPassage $editor.returnArgs[0]>>
+	<</button>>
+
+	<<set _allPassageNames = Story.lookupWith((p)=>true).map((p)=>p.title)>>
+	<<autocomplete "_openPassageName" _allPassageNames>>
+		<<set $editor.passage = _openPassageName>>
+		<<goto 'editor'>>
+	<</autocomplete>>
+</div>
+
+<div id="editor">
+
+</div>
+
+<div id="commonTasks" class="collapsable collapsed">
+	<h2>Common Tasks</h2>
+	<div class="comment">
+		This is an example of help that could be provided here.
+	</div>
+	<h3>Passage Links</h3>
+	<h4>Goto</h4>
+	<div>
+		You use a goto-command to get from one passage to another.
+		Each goto-command creates a new entry in the history.
+		The player can navigate between these steps using the arrow-buttons in the Topbar (if this isn't disabled).
+		This system breaks if goto-commands are chained.
+		<b>You should therefore avoid executing a goto-commands without user-input!</b>
+	</div>
+	<div>
+		<code>&lt;&lt;goto 'passage2'&gt;&gt;</code><br/>
+		This is the SugarCube-native way to execute a goto-command. Use it if no arguments have to be sent to the next passage.
+	</div>
+	<div>
+		<code>&lt;&lt;gt 'passage2' 'arg0' 'arg1'&gt;&gt;</code><br/>
+		This command behaves as it does in QSP: send the user to a passage and set some arguments for the receiving passage.
+		Not that the <b>arguments are not separated by commas</b>.
+	</div>
+	<div>
+		<code>&lt;&lt;run setup.qsp_gt('passage2' , 'arg0' , 'arg1')&gt;&gt;</code><br/>
+		This is the syntax you'll find in the auto-translated files.
+		It provides support for some weird edge cases (mostly concerning dynamic code).
+		If you don't need that, use one of the two previous approaches.
+	</div>
+</div>
+
+<div id="passageLinks" class="collapsable collapsed">
+	<h2>Passage Links</h2>
+	<<set _passageLinks = setup.getPassageLinks($editor.passage)>>
+
+	<<for _passageId, _passageLinkArray range _passageLinks>>
+		<<capture _passageId>>
+		<div>
+			<<link _passageId>>
+				<<set $editor.passage = _passageId>>
+				<<goto 'editor'>>
+			<</link>>: <<=_passageLinkArray.length>>x
+		</div>
+		<</capture>>
+	<</for>>
+
+	<h2>Links to this passage</h2>
+	<<set _passageLinksToCurrentPassage = setup.getPassageLinksToPassage($editor.passage)>>
+	<<for _passageId range _passageLinksToCurrentPassage>>
+		<<capture _passageId>>
+		<div>
+			<<link _passageId>>
+				<<set $editor.passage = _passageId>>
+				<<goto 'editor'>>
+			<</link>>
+		</div>
+		<</capture>>
+	<</for>>
+
+	<div class="comment">
+		These lists might be incomplete. Some connections can not be detected automatically or it isn't efficient to do so.
+	</div>
+</div>
+
+<div id="changedFiles" class="collapsable collapsed">
+	<h2>Changed Files</h2>
+	<div class="changedPassages">
+		<<for _passage, _changes range _changedFiles>>
+			<<set _diffId = "diff_"+_passage>>
+			<<capture _passage _changes _diffId>>
+				<div class="changedPassage">
+					<h3 class="passageName">_passage</h3>
+					<<link "Open">>
+						<<set $editor.passage=_passage>>
+						<<goto 'editor'>>
+					<</link>>
+					<<linkreplace "Diff">>
+						<<run setup.placeDiffInDom(_passage,window.SweetCube.originalPassageContents[_passage],_changes,"#"+_diffId)>>
+					<</linkreplace>>
+					<<link "Delete">>
+						<<run delete _changedFiles[_passage]>>
+						<<run localStorage.setItem("SweetCube.Modifications",JSON.stringify(_changedFiles))>>
+						<<run location.reload()>>
+					<</link>>
+					<code @id=_diffId class="diff"></code>
+				</div>
+			<</capture>>
+		<</for>>
+	</div>
+</div>
+
+<<done>>
+	<<run setup.startEditor('editor',Story.get($editor.passage).text)>>
+	<<run $(".collapsable > h2:first-of-type").on("click",function() {$(this).parent('.collapsable').toggleClass('collapsed');})>>
+<</done>>
+

+ 35 - 0
qsrc2tw/twine-code/editor/diff.js

@@ -0,0 +1,35 @@
+setup.placeDiffInDom = (title, oldContent, newContent, domSelector) => {
+	setup.externalCodePromise('diff').then(()=>{
+
+		const escapedChars = {
+			/*'&' : '&amp;',
+			'<' : '&lt;',
+			'>' : '&gt;',*/
+			'"' : '&quot;',
+			"'" : '&#39;',
+			'`' : '&#96;'
+		};
+
+		for(const [toBeEscaped, asEscaped] of Object.entries(escapedChars))
+        	oldContent = oldContent.replaceAll(toBeEscaped,asEscaped);
+
+		const unifiedDiffPatch = window.Diff.createTwoFilesPatch(title,title,oldContent,newContent,undefined,undefined,{ignoreWhitespace: true, stripTrailingCr: true});
+
+		let resultingHTML = "";
+
+		unifiedDiffPatch.split('\n').forEach((line)=>{
+			if(line.startsWith('@@')){
+				resultingHTML += `<p>${line}</p>`;
+			}else if(line.startsWith('---')){
+			}else if(line.startsWith('+++')){
+			}else if(line.startsWith('-')){
+				resultingHTML += `<p class="substraction">${line}</p>`;
+			}else if(line.startsWith('+')){
+				resultingHTML += `<p class="addition">${line}</p>`;
+			}
+
+		});
+
+		$(domSelector).html(resultingHTML);
+	});
+}

+ 30 - 0
qsrc2tw/twine-code/editor/save.js

@@ -0,0 +1,30 @@
+
+setup.editorSave = (passage,newContent) => {
+    const escapedChars = {
+        '&' : '&amp;',
+		'<' : '&lt;',
+		'>' : '&gt;',
+		'"' : '&quot;',
+		"'" : '&#39;',
+		'`' : '&#96;'
+    };
+
+    let sanitizedNewContent = newContent;
+
+    for(const [toBeEscaped, asEscaped] of Object.entries(escapedChars))
+        sanitizedNewContent = sanitizedNewContent.replaceAll(toBeEscaped,asEscaped);
+
+
+    const localStorageModsKey = "SweetCube.Modifications";
+
+    const updateObject = {};
+    updateObject[passage] = sanitizedNewContent;
+
+    const currentModificationsString = localStorage.getItem(localStorageModsKey) ?? "{}";
+    const currentModifications = JSON.parse(currentModificationsString);
+    const newModifications = Object.assign({},currentModifications,updateObject);
+    const newModificationsString = JSON.stringify(newModifications);
+    localStorage.setItem(localStorageModsKey, newModificationsString);
+
+    location.reload();
+}

+ 14 - 0
qsrc2tw/twine-code/external/_external.ts

@@ -0,0 +1,14 @@
+setup.externalCodeURLs ??= {};
+setup.externalCodePromises ??= {};
+
+setup.externalCodePromise = (promiseID: string)=>{
+	if(!setup.externalCodeURLs[promiseID])
+		return Promise.resolve();
+	setup.externalCodePromises[promiseID] ??= Promise.all(
+		[
+			importScripts(setup.externalCodeURLs[promiseID].code as unknown as string), // Casting to unknown because of a weird bug in the types
+			importStyles(...setup.externalCodeURLs[promiseID].style),
+		]
+	);
+	return setup.externalCodePromises[promiseID];
+}

+ 8 - 0
qsrc2tw/twine-code/external/ace.ts

@@ -0,0 +1,8 @@
+/// <reference path="./_external.ts" />
+setup.externalCodeURLs.ace = {
+    code: [
+        "https://cdn.jsdelivr.net/npm/[email protected]/src-min-noconflict/ace.js",
+        "https://cdn.jsdelivr.net/npm/[email protected]/src-min-noconflict/theme-chrome.min.js",
+    ],
+    style:["https://cdn.jsdelivr.net/npm/[email protected]/css/ace.min.css"],
+};

+ 5 - 0
qsrc2tw/twine-code/external/diff.ts

@@ -0,0 +1,5 @@
+/// <reference path="./_external.ts" />
+setup.externalCodeURLs.diff = {
+    code: ["https://cdn.jsdelivr.net/npm/[email protected]/dist/diff.min.js"],
+    style:[],
+};

+ 5 - 0
qsrc2tw/twine-code/external/jQueryUI.ts

@@ -0,0 +1,5 @@
+/// <reference path="./_external.ts" />
+setup.externalCodeURLs.jQueryUI = {
+    code: ["https://code.jquery.com/ui/1.14.0/jquery-ui.min.js"],
+    style:["https://code.jquery.com/ui/1.14.0/themes/base/jquery-ui.css"],
+};

+ 40 - 0
qsrc2tw/twine-code/misc/getPassageLinks.ts

@@ -0,0 +1,40 @@
+const passageLinkMarkups:{[key:string]:{type:string, regex: RegExp}} = {
+	'gs-macro': 	{type: 'gs',	regex: /<<gs\s+`\['([^']+)'[^\]]*\]`\s*>>/gd},
+	'gt-function':	{type: 'gt',	regex: /setup\.qsp_gt\('([^']+)'[^\)]*\s*\)/gd},
+
+	'goto':			{type: 'gt',	regex: /<<goto\s+'([^']+)'\s*>>/gd},
+	'include':		{type: 'gs',	regex: /<<include\s+'([^']+)'\s*>>/gd},
+};
+
+setup.getPassageLinks = function(passageId:string){
+	let result:{[passageId: string]: {type: string;line: number;}[];} = {};
+
+	const passageCode = Story.get(passageId).text;
+
+	for(const[key, markupSettings] of Object.entries(passageLinkMarkups)){
+		const regex = markupSettings.regex;
+		let regexMatch;
+		while(regexMatch = regex.exec(passageCode)) {
+			const passageId = regexMatch[1];
+			result[passageId] ??= [];
+			result[passageId].push({line:-1, type: markupSettings.type});
+		}
+	}
+
+	return result;
+}
+
+setup.getPassageLinksToPassage = function(passageId:string){
+	function anyPassageLinkMarkupMatches(text:string):boolean{
+		for(const[key, markupSettings] of Object.entries(passageLinkMarkups)){
+			let regexMatch;
+			while(regexMatch = markupSettings.regex.exec(text))
+				if(regexMatch[1] == passageId)
+					return true;
+		}
+		return false;
+	}
+
+	return Story.lookupWith(function(p){return anyPassageLinkMarkupMatches(p.text)}).map((passage)=>passage.title);
+
+}

+ 30 - 0
qsrc2tw/twine-code/misc/head.txt

@@ -1 +1,31 @@
 <meta name="rating" content="adult" />
+<script>
+	window.SweetCube ??= {passageInitOverwrites:[], originalPassageContents:{}};
+
+    function applyModifications(modifications={}){
+		function applyModification(passage, modification){
+			passage.element.innerHTML = modification;
+			return passage;
+		}
+
+
+		window.SweetCube.passageInitOverwrites.push((pid,passage)=>{
+			const passageName = passage?.element?.attributes?.name?.value;
+			if(!passageName || !modifications[passageName])
+				return passage;
+
+			window.SweetCube.originalPassageContents[passageName] = passage.element.innerHTML;
+
+			const modification = modifications[passageName];
+
+			return applyModification(passage,modification);
+		});
+    }
+
+	const modificationsString = localStorage.getItem("SweetCube.Modifications");
+	if(modificationsString){
+		const modifications = JSON.parse(modificationsString);
+		applyModifications(modifications);
+	}
+
+</script>

+ 1 - 1
qsrc2tw/twine-code/start/begin.tw

@@ -15,7 +15,7 @@
 	<<SHOWSTAT 1>>
 	<h2>CHOOSE GAME START</h2>
 	<div id="beginScenarioSelection" style="display: flex;justify-content: center;">
-		<<gs `['beginScenarioSelection']`>>
+		<<gs `['beginscenarioselection']`>>
 	</div>
 	<p>
 		There are three main start types:

+ 1 - 1
qsrc2tw/twine-code/start/start.tw

@@ -11,7 +11,7 @@
 <center>Version <<=`${QSP.version_major[0]}.${QSP.version_minor[0]}.${QSP.version_revision[0]}.${QSP.version_patch[0]}`>></center>
 <center><font color="red"><b>Children under 18 years are strictly forbidden to play</b></font>
 <br/>
-<<='<center><img '+(QSP.$set_imgh[0])+' src="images/system/1_openings/splashes/splash' + setup.qsp_rand(1 , 30) + '.jpg" ></center>'>>
+<<='<center><img '+(QSP.$set_imgh[0])+' src="images/system/1_openings/splashes/splash' + setup.qsp_rand(1 , 30) + '.jpg" alt="If you see this message, your images-folder is set up incorrectly." style="color: red;font-size: 2em;font-weight: bold;" ></center>'>>
 <center>Based on the Russian game ЭТО by DeGross.</center>
 <br/>
 This game is about the simulated life of a woman containing elements of RPG, strategy, porn and magical combat.

+ 10 - 0
qsrc2tw/twine-code/twine-code.d.ts

@@ -63,6 +63,16 @@ declare module "twine-sugarcube" {
 
         qsp_dyneval: (code:string, ...args : (string|number)[]) => string|number;
         qsp_func: (passage:string,...arguments:(string|number)[]) => string|number;
+
+
+        //#region External Code
+            externalCodeURLs: {[key:string]:{code:string[],style:string[]}};
+            externalCodePromises: {[key:string]:Promise<any>};
+            externalCodePromise: (promiseId:string)=>Promise<any>;
+        //#endregion
+
+        getPassageLinks: (passageId:string) => {[passageId:string]:{type:string;line:number}[]};
+        getPassageLinksToPassage: (passageId:string) => string[];
     }
 
     export interface SugarCubeStoryVariables{

+ 36 - 0
qsrc2tw/twine-code/ui/autoComplete.ts

@@ -0,0 +1,36 @@
+Macro.add('autocomplete', {
+	skipArgs : false,
+    tags: [],
+	handler  : function () {
+		try{
+
+            const varname = this.args[0];
+            const domID = `autoComplete_${varname.replaceAll("$","--")}`;
+            const tags = this.args[1];
+
+            const innerCode = this.payload[0].contents;
+
+            $(this.output).wiki(`<<id '${domID}'>><<textbox "${varname}" "">><</id>>`);
+
+            $(document).one(':passagedisplay', function (ev) {
+                setup.externalCodePromise('jQueryUI').then(function () {
+                    $(`#${domID}`).autocomplete({
+                        source: tags,
+                        select: (event, ui) => {
+                            const v = ui.item.value;
+                            State.setVar(varname,v);
+                            $.wiki(innerCode);
+                        }
+                    });
+
+                });
+            });
+		}
+		catch (ex) {
+			return this.error('ERROR in gt-widget: ' + ex.message);
+		}
+	}
+});
+
+
+

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików