Jump to content


Photo

Fast question about scripting.


  • Please log in to reply
9 replies to this topic

#1 Emzeror

Emzeror
  • Member
  • 65 posts

Posted 22 February 2008 - 08:30 PM

IF
  Global("CheckSabrinaMatch","GLOBAL",0)
  Global("SabrinaMatch","GLOBAL",0)
  Gender("Player1",MALE)
THEN
  RESPONSE #100
	SetGlobal("CheckSabrinaMatch","GLOBAL",1)
	SetGlobal("SabrinaMatch","GLOBAL",1)	
EXIT

IF
  Global("SabrinaMatch","GLOBAL",1)
  Global("SabrinaRomanceActive",0)
THEN
  RESPONSE #100
	SetGlobal("LoveTalk","LOCALS",1)
	SetGlobal("SabrinaRomanceActive", 1)
	RealSetTimer("SabrinaRomance", 1200)
EXIT

Why are 99% of the mods using that code instead of:
IF
  Global("CheckSabrinaMatch","GLOBAL",0)
  Global("SabrinaMatch","GLOBAL",0)
  Gender("Player1",MALE)
THEN
  RESPONSE #100
	SetGlobal("CheckSabrinaMatch","GLOBAL",1)
	SetGlobal("SabrinaMatch","GLOBAL",1)	
	SetGlobal("LoveTalk","LOCALS",1)
	SetGlobal("SabrinaRomanceActive", 1)
	RealSetTimer("SabrinaRomance", 1200)
EXIT

And lastly, why is there one CheckSabrinaMatch and one SabrinaMatch, shouldn't there only need to be one SabrinaMatch?

Basicaly, why can't you even use:
IF
  Global("SabrinaMatch","GLOBAL",0)
  Gender("Player1",MALE)
THEN
  RESPONSE #100
	SetGlobal("SabrinaMatch","GLOBAL",1)	
	SetGlobal("LoveTalk","LOCALS",1)
	SetGlobal("SabrinaRomanceActive", 1)
	RealSetTimer("SabrinaRomance", 1200)
EXIT

Thanks in Advance for clearyfing this.

Edited by Emzeror, 22 February 2008 - 08:34 PM.

Shadow of Asere - Mod under development. - More information coming.

"Tales and stories long forgotten has been remembered,
evil and chaos sealed away has been found,
beware mortal, the world will tremble once again."

-- Asere

#2 Jarno Mikkola

Jarno Mikkola

    The Imp in his pink raincoat.

  • Member
  • 10911 posts

Posted 23 February 2008 - 01:59 AM

My guess is, that you can add more things than just gender to the first function, without dragging the later on the side, creating hazzards etc.

Deactivated account. The user today is known as The Imp.


#3 Yovaneth

Yovaneth

    The newly-appointed Master Builder of Baldur's Gate

  • Modder
  • 3058 posts

Posted 23 February 2008 - 02:17 AM

It's entirely possible that

Global("SabrinaMatch","GLOBAL",1)

gets set to something else, somewhere else and negates or resets the block. What you have there could simply be a first run through to set some defaults.

-Y-

#4 Emzeror

Emzeror
  • Member
  • 65 posts

Posted 23 February 2008 - 03:13 AM

So basically, Baldur's Gate is such random so variables can randomly get setted to other values? Not very stabile imo, and if I wanna add more than gender I simple do so:
Gender(Player1,MALE)
CheckStatGT(Player1,20,STR)
Alignment(Player1,MASK_EVIL)

I've tried them all out myself, and they all work as it seems. The only risk I see is if someone is messing around with "CLUAConsole:", and actually they have to pretty much blame themself there. But just for saftety I will go with the middle script then, to have to have two checks. In case something really weird happens / someone is trying their skills in CLUA.
Shadow of Asere - Mod under development. - More information coming.

"Tales and stories long forgotten has been remembered,
evil and chaos sealed away has been found,
beware mortal, the world will tremble once again."

-- Asere

#5 Kulyok

Kulyok
  • Modder
  • 2450 posts

Posted 23 February 2008 - 05:47 AM

All approaches are possible. It depends on the modder's preference.

In IWD NPC, I use this, once, and that's all. There are no timers, no lovetalk variable, and no romance active variable:

IF
Global("MyNPCMatch","GLOBAL",0)
InParty("MyNPC")
Gender(Player1,MALE)
OR(3)
Race(Player1,HUMAN)
Race(Player1,HALF_ELF)
Race(Player1,ELF)
THEN
RESPONSE #100
SetGlobal("MyNPCMatch","GLOBAL",1)
END


Only once in the course of the game, this variable changes to a different value via dialogue(or player-initiated dialogue).

#6 berelinde

berelinde

    Troublemaker

  • Modder
  • 4916 posts

Posted 23 February 2008 - 08:34 AM

Gavin is coded with something like

/* ROMANCE MATCH */
  /* Compatible */
  IF %BGT_VAR%
	InParty(Myself)
	Global("B!GavinRomanceMatch","GLOBAL",0)
	Global("B!GavinCheckRomanceMatch","GLOBAL",0)
	Alignment(Player1,MASK_GOOD)
	CheckStatGT(Player1,11,CHR)
	CheckStatGT(Player1,9,WIS)
	Gender(Player1,FEMALE)
	ReputationGT(Player1,10)
	!Kit(Player1,ASSASIN)
	!Kit(Player1,BOUNTYHUNTER)
	!Kit(Player1,MAGESCHOOL_NECROMANCER)
	!HasItemEquiped("%tutu_var%BELT05",Player1)
  THEN
	RESPONSE #100  
	  SetGlobal("B!GavinRomanceMatch","GLOBAL",1)
	  SetGlobal("B!GavinCheckRomanceMatch","GLOBAL",1)
  END
Because the very next block is
/* Not compatible */
  IF %BGT_VAR%
	InParty(Myself)
	Global("B!GavinRomanceMatch","GLOBAL",0)
	Global("B!GavinCheckRomanceMatch","GLOBAL",0)
	OR(9)
	  Gender(Player1,MALE)
	  ReputationLT(Player1,11)
	  CheckStatLT(Player1,12,CHR)
	  CheckStatLT(Player1,10,WIS)
	  !Alignment(Player1,MASK_GOOD)
	  Kit(Player1,ASSASIN)
	  Kit(Player1,BOUNTYHUNTER)
	  Kit(Player1,MAGESCHOOL_NECROMANCER)
	  HasItemEquiped("%tutu_var%BELT05",Player1)
  THEN
	RESPONSE #100
	  SetGlobal("B!GavinRomanceMatch","GLOBAL",0)
	  SetGlobal("B!GavinCheckRomanceMatch","GLOBAL",1)
  END

I did it this way because I wanted to be able to use a PID option to start the romance if the check was made, but failed, and if the player modified the character to meet the criteria.

"Imagination is given to man to console him for what he is not; a sense of humor, for what he is." - Oscar Wilde

berelinde's mods
TolkienAcrossTheWater website
TolkienAcrossTheWater Forum


#7 Emzeror

Emzeror
  • Member
  • 65 posts

Posted 23 February 2008 - 08:43 AM

Yeah but checks like that are the second step Berelinde, to begin with I won't have anything that can ruin the romance or anything like it. So it is easier for me to test it.  I just wanna know why there is a "CheckMyNpcMatch" variable, since I find it totally useless, if somehow the "MyNPcMatch" variable should be resetted, what says that "CheckMyNpcMatch" won't be resetted aswell? And the chances are very close to zero.

Also, abit off-topic but another question about scripting:
Interact() DialogueNoSet() DialgoueSet() <-- What is the differences betweeen them? Sometimes Interact() works smooth. Sometimes it don't and then I use DialogueNoSet(), and doesn't feel to well to code with /random(2) (Which function am I gonna pick?) If you get my point.

Thanks in Advance.
Shadow of Asere - Mod under development. - More information coming.

"Tales and stories long forgotten has been remembered,
evil and chaos sealed away has been found,
beware mortal, the world will tremble once again."

-- Asere

#8 Kulyok

Kulyok
  • Modder
  • 2450 posts

Posted 23 February 2008 - 08:52 AM

Interact() DialogueNoSet() DialgoueSet() <-- What is the differences betweeen them? Sometimes Interact() works smooth. Sometimes it don't and then I use DialogueNoSet(), and doesn't feel to well to code with /random(2) (Which function am I gonna pick?) If you get my point.


Short answer: always use StartDialogueNoSet, whenever you can.

Long answer: There are two main dialogue files for each joinable NPCs, B file and J file.

Dialogue from B file is called via Interact. Also, all random banter is placed into B file, because the game engine pulls random banters from B files of all joinable NPCs every few hours.
For Interact to work correctly, the characters should be close enough to each other, within the same screen.

Dialogue from J file is called via Dialogue and StartDialogueNoSet. Dialogue() means that the character approaches the player, and then strikes the conversation. This can be bad, since it often looks as if something is glitching/stuttering in-game. Play Amber mod a few times to get the feeling. If you like it, all right. If not, try -

StartDialogueNoSet() is the most popular command. It requires very little, and when it is called, the character immediately initiates dialogue with your PC. They don't have to be close to each other.

Read Weidu readme from http://weidu.org, and various dialogue tutorials at http://modlist.pocketplane.net for more information.

#9 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 23 February 2008 - 08:52 AM

Why are 99% of the mods using that code instead of:

IF
  Global("CheckSabrinaMatch","GLOBAL",0)
  Global("SabrinaMatch","GLOBAL",0)
  Gender("Player1",MALE)
THEN
  RESPONSE #100
	SetGlobal("CheckSabrinaMatch","GLOBAL",1)
	SetGlobal("SabrinaMatch","GLOBAL",1)	
	SetGlobal("LoveTalk","LOCALS",1)
	SetGlobal("SabrinaRomanceActive", 1)
	RealSetTimer("SabrinaRomance", 1200)
EXIT



And lastly, why is there one CheckSabrinaMatch and one SabrinaMatch, shouldn't there only need to be one SabrinaMatch?

Basicaly, why can't you even use:
IF
  Global("SabrinaMatch","GLOBAL",0)
  Gender("Player1",MALE)
THEN
  RESPONSE #100
	SetGlobal("SabrinaMatch","GLOBAL",1)	
	SetGlobal("LoveTalk","LOCALS",1)
	SetGlobal("SabrinaRomanceActive", 1)
	RealSetTimer("SabrinaRomance", 1200)
EXIT

Thanks in Advance for clearyfing this.


Emzeror, there are a cople of points to make here - from a practical standpoint, the one that stands out is many mods are actually doing what you are saying and placing a good deal of conditions and setting many materials at once.

example: Dynaheir, BG1NPC
/* Set Romance Match */
IF %BGT_VAR%
Global("X#DynahMatch","GLOBAL",0)
InParty(Myself)
GlobalGT("X#DyFriendTalk","GLOBAL",1)
Gender(Player1,MALE)
!Global("P#BranwenRomanceActive","GLOBAL",2)
!Alignment(Player1,MASK_EVIL)
!Alignment(Player1,CHAOTIC_NEUTRAL)
OR(4)
Race(Player1,HUMAN)
Race(Player1,ELF)
Race(Player1,HALF_ELF)
Race(Player1,HALFORC)
ReputationGT(Player1,10)
CheckStatGT(Player1,9,INT)
CheckStatGT(Player1,9,WIS)
THEN
RESPONSE #100
SetGlobal("X#DynahMatch","GLOBAL",1)
END


Reasoning behind smaller evaluative blocks:

1. interruption of the script. Remember there are many different scripts running in a hierarchy at any given time. It is hard to imagine a long script block being interrupted, given the speed of computers, but it seems to have happened; testing indicates the most stable usage seems to be smaller targeted blocks that do limited actions, and then pass on the action to another block. This becomes much more important when folks start adding many mods - Saerileth is an example of a mod that begins to bog down materials with lots of item checks and long sequences that make it tough to play if you have many other mods installed (one of the reasons I play small, targeted installs).

Look at the BioWare™ BG2 cutscenes for a good example of this chaining of small blocks of actions together instead of building a huge block that might fail/get interrupted.

2. writing process. Most mods are constructed over time, and new ideas come and go from the writing. A new variable gats added, one gets taken away - in most projects out there, the long development time means revisions. many revisions means remembering what got set where... and what got unset. Easier to do if you are keeping small blocks well labled in the code.

3. code understanding. Some mods are built by folks who want to write and are not versed in conditional blocks or state weighted logical engine approaches (myself included - it is a long, hard road to understanding). We don't want to write what we don't understand, so we might build small blocks and make them play with eachother rather than going through tons of stuff in a big block that we have to untangle later.

4. simplicity. Less is more. and simple code is easy to search, fix, and maintain. And less to go wrong. Personally,
IF <<condition>> THEN RESPONSE #100 IncrementGlobal("MyGlobal","GLOBAL",1) END
is a solid, working approach, easily dealy with. I can set a single long block running, doing that action, and all will be well.
BUT I think it is just as easy and certainly easier to troubleshoot when everything is explicitly set>>

IF <<condition>> THEN RESPONSE #100 SetGlobal("MyGlobal","GLOBAL",4) END

Now I can textsearch for 3,4,5, and find out where I messed something up in advancing the global between dialogue and baf in a few seconds, instead of painfully revisiting all the code and rebuilding it in my mind. Simpler blocks means less to look at.

why is there one CheckSabrinaMatch and one SabrinaMatch


Nothing wrong with it at all; but having the independent variable set tells you that that particular block has evanuated, with a check in NI or DLTCEP. It targets an individual block very specifically.

For testing, I often put DisplayStringHead(Myself,~1~) on each block to run, advancing the number each block. It gives me an instant read of what block is misfiring. You can'tt do that with operating installs in the field, though, so the easiest way to do it is create either an advancing global that tracks the whole progression (if it is linear) or specific variables tioed to specific actions ("C-SheriHasJustKissedPC") that can be scanned for in NI on an install in the field.


Whatever works for you and playtests out is great. The only big suggestion that has changed over the past few years about this kind of big block scripting is the change away from running all globals being set from .BCS in big huge chains of conditions "opening" a variable for a small amount of time, then "closing" it again in the same BCS. Instead, modern mods tend to use a 'ping-pong" effect between .bcs and .dlg where the script sets the variable and the dialogue closes it. Take a quick search for this, and you will find good conversations and a tutorial on it.

Edited by cmorgan, 23 February 2008 - 08:58 AM.


#10 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 26 February 2008 - 03:13 PM

So basically, Baldur's Gate is such random so variables can randomly get setted to other values? Not very stabile imo

Uhm, no. Variables don't get randomly set. That would defeat the purpose of having variables to begin with.

What Yovaneth meant was that the the modder could choose to change the value of the variable at a later stage in the mod or something similar.

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner