Jump to content


Photo

Zed Nocear's Trigger-Simulations for BG1


55 replies to this topic

#1 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 07 April 2008 - 12:08 PM

Current version from 01/14th/2012

Zed Nocear's BG1 Trigger-Simulations
This tutorial presents the simulations of BGII triggers for original BG (with or without the Add-on Tales of the Sword Coast) as defined by Zed Nocear. They are already successfully used in two BG1 mods: Zed Nocear's TWM ("Mysteries of the Sword Coast", currently only in Polish), and jastey's Ajantis BG1 Expansion Mod. The tutorial is open for discussion. If you have suggestions, corrections or other ideas please share them!

Content
1. Detection of AreaType and simulating AreaCheck()
2. Detection of "Party rested"
3. Simulating CombatCounter()


1. Detection of AreaType and simulating AreaCheck()
To simulate the AreaType() check known from BGII, all area scripts are patched to set the appropriate variables. There are two sets of scripts for patching: One for the master areas, and one for all areas that are not listed as master areas. Note: The code transfers all content of the actual area.bcs to a script that has the area name. Hence, if the area script did not have the same number/name as the area before, the name will be changed by this script.
The patching code in the tp2 is the following:

<<<<<<<< .../BG1TriggerEmulation-inlined/Z!EmulAreaCheck.BAF
IF
	Delay(2)
	ActionListEmpty()
THEN
	RESPONSE #100
		SetGlobal("Z!EmulAreaCheck","GLOBAL",%Area_Number%)
		SetGlobal("Z!EmulAreaType","GLOBAL",%Area_Flags%)
		SetGlobal("Z!EmulAreaOutdoor","GLOBAL",%Variable_Outdoor%)
		SetGlobal("Z!EmulAreaCity","GLOBAL",%Variable_City%)
		SetGlobal("Z!EmulAreaForest","GLOBAL",%Variable_Forest%)
		SetGlobal("Z!EmulAreaDungeon","GLOBAL",%Variable_Dungeon%)
		SetGlobalTimer("Z!EmulAreaNotMaster","GLOBAL",4)
END
>>>>>>>>

<<<<<<<< .../BG1TriggerEmulation-inlined/Z!EmulAreaCheck1.BAF
IF
	!Global("Z!EmulAreaCheck","GLOBAL",%Area_Number%)
	!GlobalTimerNotExpired("Z!EmulAreaNotMaster","GLOBAL")
	ActionListEmpty()
THEN
	RESPONSE #100
		SetGlobal("Z!EmulAreaCheck","GLOBAL",%Area_Number%)
		SetGlobal("Z!LastMasterArea","GLOBAL",%Area_Number%)
		SetGlobal("Z!EmulAreaType","GLOBAL",%Area_Flags%)
		SetGlobal("Z!EmulAreaOutdoor","GLOBAL",%Variable_Outdoor%)
		SetGlobal("Z!EmulAreaCity","GLOBAL",%Variable_City%)
		SetGlobal("Z!EmulAreaForest","GLOBAL",%Variable_Forest%)
		SetGlobal("Z!EmulAreaDungeon","GLOBAL",%Variable_Dungeon%)
END
>>>>>>>>

COPY_EXISTING  ~AR2612.ARE~ ~override~ // two areas in BG1 have wrong flag "Outdoor"
			   ~AR3317.ARE~ ~override~
  WRITE_BYTE 0x48 0
  BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~.*\.ARE~ ~override~ // for all areas in game proper script name and file
  SPRINT area_name ~%SOURCE_RES%~
  READ_ASCII 0x94 ~old_script_name~
  WRITE_EVALUATED_ASCII 0x94 ~%SOURCE_RES%~
  INNER_ACTION BEGIN
	ACTION_IF !(~%old_script_name%~ STRING_EQUAL_CASE ~%area_name%~)
		  AND (FILE_EXISTS_IN_GAME ~%old_script_name%.bcs~)
	  THEN BEGIN COPY_EXISTING ~%old_script_name%.bcs~ ~override/%area_name%.bcs~ END
  END
  BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~.*\.ARE~ ~override~ // adds AreaCheck emulation block to the area script
  READ_ASCII 0x94 ~Script_Name~
  PATCH_IF (~%SOURCE_RES%~ STRING_MATCHES_REGEXP ~AR[0-9][0-9][0-9][0-9]~) = 0
	THEN BEGIN READ_ASCII 0x96 ~Area_Number~ (4) END
	ELSE BEGIN SPRINT ~Area_Number~ ~0~ END
  READ_BYTE 0x48 ~Area_Flags~
  INNER_ACTION BEGIN
	ACTION_IF (NOT FILE_CONTAINS_EVALUATED(~%Script_Name%.BCS~ ~Z!EmulAreaCheck~)) // area script not already patched
	  THEN BEGIN
		OUTER_SET Variable_Outdoor = ((~%Area_Flags%~ BAND 0b1) = 0b1)
		OUTER_SET Variable_City	= ((~%Area_Flags%~ BAND 0b1000) = 0b1000)
		OUTER_SET Variable_Forest  = ((~%Area_Flags%~ BAND 0b10000) = 0b10000)
		OUTER_SET Variable_Dungeon = ((~%Area_Flags%~ BAND 0b100000) = 0b100000)
		ACTION_IF (FILE_CONTAINS_EVALUATED(~MASTAREA.2DA~ ~%Script_Name%~))
		  THEN BEGIN EXTEND_BOTTOM ~%Script_Name%.BCS~ ~.../BG1TriggerEmulation-inlined/Z!EmulAreaCheck1.BAF~ EVALUATE_BUFFER END //area is "master area" as in mastarea.2DA
		  ELSE BEGIN EXTEND_BOTTOM ~%Script_Name%.BCS~ ~.../BG1TriggerEmulation-inlined/Z!EmulAreaCheck.BAF~  EVALUATE_BUFFER END //area is not "master area"
	END
  END
  BUT_ONLY_IF_IT_CHANGES


The code can be downloaded as tpa here: BG1areacheck_emulation.tpa (3KB)

Now, including the tpa into your mod, installation only needs the following line in the tp2:
INCLUDE ~%PatchInMyMod%/BG1AreaCheck_emulation.tpa~


"Z!EmulAreaType" gives the sum of all flags (value of the offset 0x48) of the according ARE-Datei.
The triggers AreaType() and AreaCheck() can be simulated:

AreaType():
OUTDOOR: "Global("Z!EmulAreaOutdoor","GLOBAL",1)"
CITY: "Global("Z!EmulAreaCity","GLOBAL",1)"
FOREST: "Global("Z!EmulAreaForest","GLOBAL",1)"
DUNGEON: "Global("Z!EmulAreaDungeon","GLOBAL",1)"

AreaCheck()
For simulating AreaCheck(), the variable "Z!EmulAreaCheck" can be used: For the original BG areas, the value of the variable is equal to the "ARxxxx" number. For (mod) areas that are not named like the standard "ARxxxx", the variable is equal to "0".
For example, now the Area AR2600 can be detected via the trigger "Global("Z!EmulAreaCheck","GLOBAL",2600)".


2. Detection of "Party rested"
To simulate the "PartyRested()" trigger known from BGII, the FATIGUE state of the Player1 will be used. Directly after rest, this stat has the value "0". During the game, it increases until the character reached a state of fatigue. For detection of the rest, the FATIGUE value will be checked. If it is "0", the custom spell "Z!FATIG1" sets the FATIGUE value to "1", along with the setting of the needed timers for the after-rest dialogues.

(Note: Theoretically, this means that the character will fatigue faster in the game (4 hours earlier). So far, this could not be detected in the game while playing with this party rested detection installed, though.)

For this, dplayer3.bcs is patched with the following script block. The example is for the Ajantis romance in the BG1 Ajantis expansion modification. Own variables and timers have to be inserted in your mod, accordingly:
//dplayer3_add.baf
IF
	CheckStat(Player1,0,FATIGUE)
THEN
	RESPONSE #100
		ApplySpellRES("Z!FATIG1",Player1)
		IncrementGlobal("X#AjantisRomanceRestCounter","GLOBAL",1)
		SetGlobalTimer("X#AjantisRomanceRestAfterTimer","GLOBAL",30)
END

Thus, the needed triggers for the dialogues will be given after the rest, i.e. if the FATIFUE value was at "0". For a short period after wake-up, the timer "X#AjantisRomanceRestAfterTimer" runs and can be used to trigger morning dialogues.


For the Ajantis morning dialogue, the triggering script block looks like this:

/* dialogue activation */
IF
	InParty(Myself)
	!StateCheck(Myself,CD_STATE_NOTVALID) //custom state from CamDawg
	!StateCheck(Player1,CD_STATE_NOTVALID)
	Detect(Player1)
	!See([ENEMY])
	!GlobalTimerNotExpired("Z!EnemySeenPeriod","GLOBAL") //simulation of CombatCounter(0), see below
	!Global("X#AjantisRomanceActive","GLOBAL",3)
	Global("X#AjantisRomanceMatch","GLOBAL",1)
	GlobalGT("X#AjantisRomanceRestCounter","GLOBAL",1) //greater as 1: the first time the variable is incremented is directly after the installation!
	!GlobalTimerExpired("X#AjantisRomanceRestAfterTimer","GLOBAL") //timer runs: dialogue triggers shortly after wake-up
	Global("X#AjantisRomanceStars","GLOBAL",1)
THEN
  RESPONSE #100
	SetGlobal("X#AjantisRomanceStars","GLOBAL",3)
END

/* dialogue triggering */
IF
	InParty(Myself)
	!StateCheck(Myself,CD_STATE_NOTVALID)
	!StateCheck(Player1,CD_STATE_NOTVALID)
	Global("X#AjantisRomanceStars","GLOBAL",3)
THEN
  RESPONSE #100
	SetGlobalTimer("X#AjantisRomance","GLOBAL",TWO_DAYS)
	Dialogue(Player1)
END

Now the crucial part: Making the PartyRested() simulation compatible with other mods. For this, a distinction of cases has to be put into the tp2-files. With this disctinction, the above posted patching of the dplayer3.bcs will only happen, if no other mod already patched the application of the spell. If another mod already did so, patching of the appropriate script block is not only sufficient for your mod, but the only way to keep the mods compatible.

So, the tp2 section looks like this:
APPEND ~action.ids~ ~160 ApplySpellRES(S:ResRef*,O:Target*)~	   UNLESS ~ApplySpellRES~

ACTION_IF (FILE_CONTAINS_EVALUATED (~dplayer3.BCS~ ~"Z!FATIG1"~))
	THEN BEGIN
		COPY_EXISTING ~dplayer3.BCS~ ~override~
			DECOMPILE_BCS_TO_BAF
			REPLACE_TEXTUALLY ~ApplySpellRES("Z!FATIG1",Player1)~
											 ~ApplySpellRES("Z!FATIG1",Player1)
												IncrementGlobal("X#AjantisRomanceRestCounter","GLOBAL",1)
											   SetGlobalTimer("X#AjantisRomanceRestAfterTimer","GLOBAL",30)~
			COMPILE_BAF_TO_BCS
	END
	ELSE BEGIN
		EXTEND_TOP ~dplayer3.BCS~ ~C#AjantisRomance_BG1/TriggerSimulations/dplayer3_add.BAF~
		COPY ~TWM_Pack/00RESTcheck/Z!FATIG1.SPL~ ~override~
	END

The spell can be downloaded here: Download Z!FATIG1.SPL.RAR (120 kB)
The .zip contains the spell, which has to be copied to the override folder.


3. Simulating CombatCounter()
To simulate the trigger "CombatCounter(0)" known from BGII, the override scripts of the NPCs, the dplayer3.bcs (for the PC), and dplayer2.bcs (for mod-NPCs that do not use the enemy detection in their scripts) are patched with a script block that runs a timer as soon as one of the NPCs see an enemy. Note: dplayer2.bcs only gets executed, if the AI is turned on in the game. The override script of an NPC is the only one that gets executed with tuned off AI.

The script for patching is the following (in the following referred to as "CombatTimer_add.BAF"):
IF
   Global("Z!EnemyAlreadySeen","LOCALS",0)
   InParty(Myself)
   See([ENEMY])
   ActionListEmpty()
THEN
   RESPONSE #100
	  SetGlobal("Z!EnemyAlreadySeen","LOCALS",1)
END

IF
   Global("Z!EnemyAlreadySeen","LOCALS",0)
   InParty(Myself)
   Died([ENEMY])
THEN
   RESPONSE #100
	  SetGlobal("Z!EnemyAlreadySeen","LOCALS",1)
END

IF
  InParty(Myself)
  !See([ENEMY])
  Global("Z!EnemyAlreadySeen","LOCALS",1)
THEN
RESPONSE #100
  SetGlobal("Z!EnemyAlreadySeen","LOCALS",0)
  SetGlobalTimer("Z!EnemySeenPeriod30","GLOBAL",30) // halbe Minute, halbe Tour im Spiel
  SetGlobalTimer("Z!EnemySeenPeriod60","GLOBAL",60) //eineMinute, volle Tour im Spiel
  SetGlobalTimer("Z!EnemySeenPeriod150","GLOBAL",150) //reale 2,5 Minuten, halbe Stunde im Spiel
  SetGlobalTimer("Z!EnemySeenPeriod900","GLOBAL",900) // drei Stunden im Spiel
  SetGlobalTimer("Z!EnemySeenPeriod7200","GLOBAL",7200) // Tag und Nacht im Spiel
END

Now the BGII trigger "CombatCounter(0)" can be simulated using the trigger

"!See([ENEMY])
!GlobalTimerNotExpired("Z!EnemySeenPeriodX","GLOBAL")"

for the relevant NPC, with "X" being the wanted time interval: 60, 150, 900, 7200.

For patching, it is useful to check whether the script blocks were already added. For Ajantis override script, this would look like this:
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~ajantis.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~ajantis.BCS~  ~AjantisBG1/BG1_TriggerSimulations/combatcounter.baf~
  END
in the .tp2.

Note: Not every BioWare BG1 NPCs have override scripts.
NPCs who do not have override scripts are: Alora, Branwen, Faldorn, Garrick, Imoen, Skie, and Xan.

Imoen.bcs is used for the imoen.cre (the "Imoen" the PC meets in Candlekeep). If patching the joinable "Imoen" creature files, this one should be left out.
Alora*.cres use "alora.bcs" as class script, which additionally has faulty script blocks that would block any mod script blocks that get added via EXTEND_BOTTOM. Class scripts can get deactivated by turning off the AI in the game. To have a standard concerning "override scripts of the NPC have the name of the NPC", it is suggested 1. to patch the alora.bcs as override script and 2. to correct the faulty script blocks (deleting them).

The code for the tp2-patching to achieve all this would look like this:
//Give BioWare NPCs override scripts
COPY_EXISTING_REGEXP GLOB ~^alora[0-9]*\.cre~ ~override~
	WRITE_ASCII SCRIPT_OVERRIDE ~alora~
	READ_ASCII SCRIPT_CLASS ~Class_Script_Name~
	PATCH_IF ( ~%Class_Script_Name%~ STRING_EQUAL_CASE ~alora~ ) //only class script ~Alora~ will be deleted

		THEN BEGIN
			WRITE_LONG 0x250 0x00000000
			WRITE_LONG 0x254 0x00000000
		END
	BUT_ONLY_IF_IT_CHANGES
COPY_EXISTING ~alora.BCS~ ~override~
	REPLACE_BCS_BLOCK ~Modfolder/alora_old.baf~ ~Modfolder/alora_new.baf~ //delete bad blocks
	BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^branwe[0-9]*\.cre~ ~override~
	WRITE_ASCII SCRIPT_OVERRIDE ~branwen~
   BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^faldor[0-9]*\.cre~ ~override~
	WRITE_ASCII SCRIPT_OVERRIDE ~faldorn~
   BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^garric[0-9]*\.cre~ ~override~
	WRITE_ASCII SCRIPT_OVERRIDE ~garrick~
   BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^imoen[0-9]+\.cre~ ~override~ // imoen1,2,4,6.CRE but not imoen.CRE
	WRITE_ASCII SCRIPT_OVERRIDE ~imoen~
   BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^skie[0-9]*\.cre~ ~override~
	WRITE_ASCII SCRIPT_OVERRIDE ~skie~
   BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING_REGEXP GLOB ~^xan[0-9]*\.cre~ ~override~
   WRITE_LONG 0x248 0x00000000  
   WRITE_LONG 0x250 0x00000000  
   WRITE_ASCII SCRIPT_OVERRIDE ~xan~
   BUT_ONLY_IF_IT_CHANGES

//patching der Skripte für die CombatCounter() simulation
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~dplayer3.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~dplayer3.BCS~ ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~dplayer2.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~dplayer2.BCS~ ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~ajantis.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~ajantis.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~alora.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~alora.BCS~	~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~branwen.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~branwen.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~coran.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~coran.BCS~	~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~dynaheir.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~dynaheir.BCS~ ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~edwin.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~edwin.BCS~	~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~eldoth.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~eldoth.BCS~   ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~faldorn.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~faldorn.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~garrick.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~garrick.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~imoen.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~imoen.BCS~	~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~jaheira.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~jaheira.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~khalid.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~khalid.BCS~   ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~kagain.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~kagain.BCS~   ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~kivan.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~kivan.BCS~	~Modfolder/Z!CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~minsc.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~minsc.BCS~	~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~montaron.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~montaron.BCS~ ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~quayle.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~quayle.BCS~   ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~safana.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~safana.BCS~   ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~sharteel.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~sharteel.BCS~ ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~skie.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~skie.BCS~	 ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~tiax.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~tiax.BCS~	 ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~viconia.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~viconia.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~xan.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~xan.BCS~	  ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~xzar.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~xzar.BCS~	 ~Modfolder/CombatTimer_add.BAF~
  END
ACTION_IF (NOT FILE_CONTAINS_EVALUATED (~yeslick.BCS~ ~Z!EnemyAlreadySeen~))
  THEN BEGIN
	EXTEND_BOTTOM ~yeslick.BCS~  ~Modfolder/CombatTimer_add.BAF~
  END

With alora_old.baf:

IF
	TimeOfDay(DAY)
THEN
	RESPONSE #100
		Activate(Myself)
END

IF
	TimeOfDay(DAY)
THEN
	RESPONSE #100
		Deactivate(Myself)
END

And the alora_new.baf being an empty file.

Edited by jastey, 31 July 2013 - 07:03 AM.


#2 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 6913 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 07 April 2008 - 01:15 PM

Cool ideas and workarounds, especially the spell simulation of resting. I wonder, is it interruptable? If it is, then I guess a cutscene?
I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#3 Icendoan

Icendoan

    King of Parsing Errors

  • Modders
  • 1704 posts
  • Gender:Male
  • Location:The hall of 1000 posts!

Posted 07 April 2008 - 02:17 PM

ReallyForceSpell() it?

(I checked the IESDP, so it should work)

Icen
Mods in development: Keeping Yoshimo
Posted Image

#4 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 08 April 2008 - 12:22 AM

I wonder, is it interruptable? If it is, then I guess a cutscene?

Would you explain what exactly interruptable means in this context. I never really understood that. Do you mean the script execution, where all the variables and times are set after throwing the spell could be interrupted before all variables got set?

Icendoan: You mean ReallyForceSpell() the "morning" spell? I have little experience with spell actions, does this really use a spell that is memorized?

#5 Kulyok

Kulyok
  • Members
  • 5587 posts
  • Gender:Female
  • Location:Moscow, Russia

Posted 08 April 2008 - 12:26 AM

That's incredible! I applaud the efforts in simulating AreaChecks in particular - simple and feasible.

Same goes for CombatCounter() - alas, this one is completely useless in IWD.

Edited by Kulyok, 08 April 2008 - 12:28 AM.


#6 Icendoan

Icendoan

    King of Parsing Errors

  • Modders
  • 1704 posts
  • Gender:Male
  • Location:The hall of 1000 posts!

Posted 08 April 2008 - 02:27 AM

ReallyForceSpell() (from the IESDP) says that you do not even have to have the spell in any shape or form in order to instantly cast it, without interuptions.

Icen
Mods in development: Keeping Yoshimo
Posted Image

#7 Guest_jastey*_*

Guest_jastey*_*
  • Guests

Posted 08 April 2008 - 02:38 AM

Then it is not useful for the "morning detection" spell casting, since the whole point is about detecting whether the PC has a certain memorized spell available or not.
If it's available, it means the PC rested (i.e. all spells are freshed up). It gets cast, and all variables and timers for possible NPC morning actions get set in the dplayer3.bcs, and can be used as triggers in the NPC's scripts.

#8 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 25 May 2008 - 11:39 AM

Zed Nocear found out, that the detection spell for the "resting detection" is multiplaying itself by exporting and importing the PC. He changed the version of the spell SPIN796.SPL that applies the spell on the PC, so that earlier version(s) will be removed. The download is updated, please make sure you have the current version if you want to use it in your mod.

#9 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 05 September 2008 - 10:43 AM

Update: Included the timer "GlobalTimer("Z!EnemySeenPeriod30","GLOBAL",30)" as shortest timer for CombatCounter() simulation.

#10 plainab

plainab

    Sasha al'Therin

  • Members
  • 1717 posts
  • Gender:Male
  • Location:Lost on the Sword Coast

Posted 05 September 2008 - 02:41 PM

Some of this sounds interesting. I've had to do my own work arounds for the BG Fixpack, due to the lack of AreaCheck(). Would it be acceptable to include the AreaCheck()/AreaType() 'triggers' in the BG Fixpack with/without totsc? By appearances it looks as if future installs of the same code would do a file by file check and add the needed script blocks if an added area did not have them.

However, I do see a potential issue (if there are any areas like the Crooked Crane in BG2). The area script reference should be read and checked to see if it exists prior to assigning a new name, just in case an area should have an existing script that doesn't match the area name. It's simple to do, but every following mod would need to read the script ref and use that, or blindly go with the script matches area name method instead of blindly doing what they saw in the default game. However, I don't remember if any bg1 areas are like the Crooked Crane.

Here's an example of what I mean;
COPY_EXISTING_REGEXP GLOB ~.*\.ARE~ ~override~
SPRINT filename ~%SOURCE_RES%~
READ_ASCII 0x94 ~script_name~
//go ahead and write because matching names will still match
WRITE_EVALUATED_ASCII 0x94 ~%SOURCE_RES%~ 
//see if odd named script file exists, if so copy to correct name.
INNER_ACTION BEGIN
ACTION_IF !(~%script_name%~ STRING_EQUAL_CASE ~%filename%~)
		  AND (FILE_EXISTS_IN_GAME ~%script_name%.bcs~) THEN BEGIN
 COPY_EXISTING ~%script_name%.bcs~ ~override/%filename%.bcs~
END
END
//read new for rest of patch
READ_ASCII 0x94 ~script_name~ 
/* do the rest of the patch */
BUT_IF_ONLY_IT_CHANGES

My working mods:
an AI Party Script for BG2 game engine DOWNLOAD LINK ONLY!
Interactive Tweaks for BG series with some IWD support. DOWNLOAD LINK ONLY!
Rest For 8 Hours an IWD mod
-------------------------------------------
My contributions: BG1Fixpack, BG1Tweaks
On Hold: Solestia an NPC for SOA
-------------------------------------------
My website: http://sasha-altheri...s.com/index.htm

#11 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 05 September 2008 - 09:26 PM

Including these checks would be cool! (I hope this doesn't start a discussion about what the scope of a fixpack is, though).
I am sure Zed Nocear would agree to it, too.

I know what you mean with the patching, your code is more general. I think I understand what it does. I'll ask you again how I'd have to change the above code to make it as general as yours if I had the time to look at it more closely.

#12 plainab

plainab

    Sasha al'Therin

  • Members
  • 1717 posts
  • Gender:Male
  • Location:Lost on the Sword Coast

Posted 06 September 2008 - 04:20 AM

Including these checks would be cool! (I hope this doesn't start a discussion about what the scope of a fixpack is, though).
I am sure Zed Nocear would agree to it, too.

I know how to avoid some of the 'discussions' that might arise.
1) There are things within the game that could be properly done with an area check. (don't have to be, but could be)
2) Provide code as an optional install after all "true fixes" have been installed.
3) Start a public thread about how these are needed for certain mods and that if they were included in the "Fixpack" or in a "Companion to the Fixpack" (which would require being installed second) then other mods could take advantage of the new trigger methods provided.

Sounds to me like we've already got all that here. As long as Zed is fine with it, I'll put a copy of it at the 'END' of the Fixpack. If there is still an issue with some people, I've got no problem putting it into a companion mod (distributed with the fixpack)

I know what you mean with the patching, your code is more general. I think I understand what it does. I'll ask you again how I'd have to change the above code to make it as general as yours if I had the time to look at it more closely.

When you've got the time, don't hesitate to ask. I may not have the time then, but I'd get back as quickly as I could.

I can explain it real simple (as clear as mud even) :laugh: :
1) read the script reference you want to change
2) check to see if it exists
3) if it does not exist assign the name you want
4) if it does exists and doesn't match the name you want, copy the script and give it the name you want. This ensures that any previous code gets carried over to the new script. With one caveat, any mods installed after would need to read the reference value rather than assuming that whatever was previously in that field is correct. All mods should do this, but we are lazy and don't program it.
5) re read the script reference so the new value is fresh in weidu memory
6) do the rest of the patch.
My working mods:
an AI Party Script for BG2 game engine DOWNLOAD LINK ONLY!
Interactive Tweaks for BG series with some IWD support. DOWNLOAD LINK ONLY!
Rest For 8 Hours an IWD mod
-------------------------------------------
My contributions: BG1Fixpack, BG1Tweaks
On Hold: Solestia an NPC for SOA
-------------------------------------------
My website: http://sasha-altheri...s.com/index.htm

#13 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 06 September 2008 - 06:20 AM

Sounds like a good approach. Zed Nocear will see this eventually, I left him a note. I am sure he has no objections.

#14 Zed Nocear

Zed Nocear
  • Members
  • 31 posts
  • Gender:Male

Posted 10 September 2008 - 10:03 PM

I agree to both issues. It means however, that we must again change the code for Ajantis BG1 mod, MotSC (TWM) and in Tutorial.

Maybe this part of planab's code will be more easy to understend in tutorial with small cosmetic changes of variables names:
COPY_EXISTING_REGEXP GLOB ~.*\.ARE~ ~override~
SPRINT area_name ~%SOURCE_RES%~
READ_ASCII 0x94 ~old_script_name~
//go ahead and write because matching names will still match
WRITE_EVALUATED_ASCII 0x94 ~%SOURCE_RES%~ 
//see if odd named script file exists, if so copy to correct name.
INNER_ACTION BEGIN
ACTION_IF !(~%old_script_name%~ STRING_EQUAL_CASE ~%area_name%~)
		  AND (FILE_EXISTS_IN_GAME ~%old_script_name%.bcs~) THEN BEGIN
COPY_EXISTING ~%old_script_name%.bcs~ ~override/%area_name%.bcs~
END
END
//read new for rest of patch
READ_ASCII 0x94 ~script_name~ 
/* do the rest of the patch */
BUT_IF_ONLY_IT_CHANGES


#15 jastey

jastey
  • Gibberlings
  • 5150 posts
  • Gender:Female

Posted 11 September 2008 - 09:55 AM

Changing the code is no problem. I hope I will have time for this this week-end.



Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users