Ted's RPG Rant

A place to rant about RPG games, particularly the Temple of Elemental Evil. Co8 members get a free cookie for stopping by. Thats ONE cookie each, no seconds.

Thursday, October 18, 2007

KotB Scripts

Since I can't update KECIK! from work, I may as well write a tutorial.

The following is a list of some of the new scripts being used in KotB. These may be updated in the future.

First and foremost, there is the npc flags. Folks who read Flags Tutorial 2 will remember it dealt with object flags - not OF_OFF and such, but individual flags for individual objects. The one we particularly played with was

attachee.obj_get_int( obj_f_npc_pad_i_5 ) &

attachee.obj_set_int( obj_f_npc_pad_i_5, 1 )

which was a simple way of storing a variable attached to the object. Cerulean used it for keeping track of recruitable shopkeepers as part of his fix that if you let them go, they returned to being shopkeepers (by having two - one to adventure, the other to remain attached to the shop inventory).

Anyways, in KotB I have written a very simple script to allow you to easily use these integers: it is in Scripts.py. It simply uses them as on-off flags (like game.global_flags[]) and is accessed in the following manner:

Firstly, put

from scripts import *

in the py file of the character that is going to use it, much the same way you use 'from utilities import *'.

Secondly, to set one of the flags, just use

npc_1(npc) or npc_1(attachee) depending on whether it is used from a dlg or py file.

There are 3 of these flags, called (funnily enough) npc_1, npc_2 and npc_3. Now, if you set them with npc_1(npc) (or npc_2(npc)...) you read them with

get_1(npc), get_2(npc) and get_3(npc)

Want to set one back to 0? Use

npc_1_undo(npc)

I wonder why I did it that way and not just undo_1(npc)? Heh... must have had a reason.

Anyways, here is an example of it in action from of one of the Watchmen in the Outer Bailey, who makes sure you have your weapons sheathed:

{750}{Citizen! Sheathe those weapons - it is an offense to show naked blades in the Keep.}{Citizen! Sheathe those weapons - it is an offense to show naked blades in the Keep.}{}{}{}{npc_1(npc); npc.reaction_adj( pc, -5 )}

{760}{Citizen! I have told you before, the carrying of naked blades is an offense in the Keep. If this happens again I will have to take further measures.}{Citizen! I have told you before, the carrying of naked blades is an offense in the Keep. If this happens again I will have to take further measures.}{}{}{}{npc_2(npc); npc.reaction_adj( pc, -5 )}

{770}{Citizen! Once again I find you walking the Keep with weapons in hand. This cannot continue. The standard fine is 10 gold: perhaps this will help you to remember to obey the laws.}{Citizen! Once again I find you walking the Keep with weapons in hand. This cannot continue. The standard fine is 10 gold: perhaps this will help you to remember to obey the laws.}{}{}{}{npc_3(npc); npc.reaction_adj( pc, -5 )}

{790}{Citizen! I am at a loss... once again you stand here with weapons drawn. Do you wish the whole garrison to fight you? Enough is enough. You are under arrest.}{Citizen! I am at a loss... once again you stand here with weapons drawn. Do you wish the whole garrison to fight you? Enough is enough. You are under arrest.}{}{}{}{}


So in 750, 760 and 770 we see each of the 3 flags being set. And what subsequent effect does setting these flags have? Well, if we check the heartbeat file we see that depending on which of the flags are set, the Watchman will automatically escalate his response:

if sheathed(attachee, obj):
________if get_3(attachee):
________________obj.begin_dialog( attachee, 790 )
________elif get_2(attachee):
________________obj.begin_dialog( attachee, 770 )
________elif get_1(attachee):
________________obj.begin_dialog( attachee, 760 )
________else:
________________obj.begin_dialog( attachee, 750 )

Obj is defined as any PC in range. This is a fragment of the heartbeat file, of course.

By doing it this way, it means Watchmen can react as individuals: if that particular guard has busted you before, he will remember it and be suitably unimpressed. If it is someone new who doesn't know you, they will treat it as a first offence. All this without tying up a bunch of global flags.

By now you are wondering precisely what 'sheathed' is: this is a script written for me by Darmagon, for memory. This one is in guards.py, so you put 'from guards import *' in your .py file if you want to use it.

def sheathed(attachee, triggerer):
________for pc in game.party:
________________if pc.type == obj_t_npc:
________________________return 0
________________else:
________________________weap = pc.item_worn_at(3)
________________________if weap != OBJ_HANDLE_NULL:
________________________________if (weap.obj_get_int(obj_f_material) != mat_wood):
________________________________________return 1
________return

Obviously the point of this is to check if you have your weapons sheathed. So we see firstly it only deals with folks in the party (not mercenaries, who can't be unequipped). Secondly it checks if the party member is a PC or an NPC follower, and if it is an NPC it just ignores it (I forget why, but again I had a reason). If it is a PC, it checks if the PC has something equipped at their primary weapon slot: slot 3, as detailed by Darmagon in the Well Whaddya Know? thread:

Item slot as per item_worn_at

0-hat/eyeglasses
1 necklace
2 gloves
3 primary weapon
4 secondary weapon / big shield
5 armor
6 primary ring
7 secondary ring
8 boots
9 ammo
10 cloak
11 2nd shield spot/ buckler spot
12 robe
13 bracers
14 bard's instrument
15 thieves tools


If there is something there in the slot (ie it does NOT return a null finding - gotta love those double negatives) then it checks if it is made of wood. If not, (finally) it returns a 1, so our initial query from the guard:

if sheathed(attachee, obj)

having returned a 1, goes ahead and fires: otherwise it doesn't. (The 'wood' thing, btw: most wooden weapons - crossbows, heavy flails, spears, staves, longbows etc - cannot be 'sheathed' in the convetional sense, so are exempt. I thought it was a distinction worth making).

Now, what happens if the guard finds you have got something equipped? Other than the dialogue, an unequip script will run (since asking the player to go around and do it manually is pretty ordinary). That is also in the guards script, and calling it looks like this:

{755}{Make sure it does not happen again.}{Make sure it does not happen again.}{}{}{}{unequip( 3, pc); unequip( 4, pc)}

The script being called looks like this (again it is a Darmagon):

def unequip( slot, npc):
________for npc in game.party:
________________item = npc.item_worn_at(slot)
________________if item != OBJ_HANDLE_NULL:
________________________if (item.obj_get_int(obj_f_material) != mat_wood):
________________________________holder = game.obj_create(1004, npc.location)
________________________________holder.item_get(item)
________________________________npc.item_get(item)
________________________________holder.destroy()
________return

This little script unequips the party members by creating a spare container ('holder'), moving the weapon in the slot over to the container, moving it back to the party member (where-in it will simply reappear in their inventory and not be equipped) then the holder is destroyed. Funky.

Note that by calling this twice for slot 3 then slot 4, it unequips both the primary and secondary slots. Also note that that it doesn't distinguish between NPCs and PCs - it unequips everyone in the party for thoroughness. So your NPCs are set up to behave like everyone else, but if they re-equip through some heartbeat moment (if they are kicked out then rejoined for soem internal reason, or some such thing) the party are not penalised by having this show up as a weapon-bearing moment to the guards.

That'll do for now :-)

0 Comments:

Post a Comment

<< Home