View Full Version : Repeated commands
Alavin Thu, 8th Apr '04, 7:37pm In my module, there's an item which I want to deal damage to the wearer over time, D4/round, which can't be removed until Remove Curse is cast upon the character. I've managed to get myself confused with the scripting. Could anyone help, please?
BigStick Thu, 8th Apr '04, 9:58pm Most likely, but you'll have to post what you've got so far if you want help on it. Also include where you've placed the scripts. My guess would be the module OnHeartbeat for the damage, but maybe you've got it elsewhere.
Alavin Thu, 8th Apr '04, 10:18pm The basics would be under the OnPlayerEquipItem, the beginning of which would be:
object oNecklace = GetPCItemLastEquipped();
object oPC = GetPCItemLastEquippedBy();
int nDamage = random(4);
if (oNecklace == GetObjectByTag(MirabelleNecklace))
{
while (GetLocalInt(oPC) == 0) do
{
EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING, DAMAGE_POWER_NORMAL);
ActionWait(6.0);
}
After this, the bit I haven't written yet, a variable is set to 1 if Remove Curse is cast, and the item is destroyed. The rest I have little idea about.
konny666 Fri, 9th Apr '04, 4:55am you have most of the syntax wrong there; i assume that's just pseudocode?
here is a breakdown of what you need to script for a cursed item:
1. OnModuleHeartbeat: check for localint flag on the PCs. (if this is a single-player mod with only one PC, just use "GetFirstPC". if its a multiplayer mod, you'll need to loop through all PC's in the PC faction) if this flag is found, damage will be applied. if the flag is not found, nothing happens.
2. OnPlayerEquipItem: check if item equipped is cursed item. If so, set a flag on the PC. maybe play a floaty message saying "You experience a strange magical sensation as you equip the gauntlet"
3. OnPlayerUnEquipItem: check if item unequipped is the cursed item. If so, re-equip it, and maybe pop up a floating message on the PC like "You can't remove the cursed gloves from your hands!"
4. If there is a unique NPC who is the only one who can remove the curse, have him reset the PC's flag upon "fake-casting" the spell. If the curse can be lifted from a simple "Remove Curse" spell, you can utilize the SpellHook system (introduced in Hordes) to script the removal of the PC's flag upon casting of the spell.
Note that there are ways of doing this without using module heartbeat, but that's only needed for CPU-conscious persistent worlds. Also, try to stay away from using "while" loops, that's the easiest way for a coding mistake to result in a TMI (an error which causes the currently-running script to crash).
Hope that helps.
BigStick Fri, 9th Apr '04, 2:18pm My solution is a bit different than the one above in that I don't use the module heartbeat. Here are the two scripts that I came up with to recognize that the character has been cursed and to apply the damage.
// In OnPlayerEquipItem
void main
{
object oCursedItem = GetPCItemLastEquipped();
object oPC = GetPCItemLastEquippedBy();
if (GetTag(oCursedItem) == "CursedItemTag") {
SetLocalInt(oPC, "CursedItemEquipped", 1);
ExecuteScript("CurseDamage", oPC);
} // end-if
}This one just has to be compiled in your module:
// Applies damage from cursed item every round while the character
// has the item equipped
void CurseDamage
{
if (GetLocalInt(oPC, "CursedItemEquipped")) {
int nDamage = d4();
// Use DAMAGE_POWER_ENERGY to get around any resistance
effect eOuch = EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING,
DAMAGE_POWER_ENERGY);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eOuch, oPC);
// Wait until next round and run this again.
DelayCommand(6.0, ActionDoCommand(ExecuteScript("CurseDamage", oPC)));
} // end-if
}Using the bludgeoning damage type seems odd to me, I'm picturing the necklace flopping and banging around on the PC's neck and doing damage that way... If that's what you're after, perhaps some other effects would be appropriate as well, like lowered DEX and/or Concentration. That presents a funny picture. :D
I haven't tested this or even checked to see if it compiles since I'm at work and just writing it off the cuff, but it should be close.
You'll still have to determine when the Remove Curse spell has been cast and change the "CursedItemEquipped" flag to 0, or remove the variable. You should be able to do that using the suggestion #4 from above. I like the SpellHook idea, but haven't used it yet. You'll also need to do #3 above to keep the item equipped on the PC.
This approach avoids using the module heartbeat since most of the time, hopefully, the character won't have the item equipped. It will also work for as many players as needed since it assigns the character the task of running the damage script.
Alavin Fri, 9th Apr '04, 4:28pm It's supposed to be that the chain around the neck tightens slowly, rather than a huge necklace whacking the hell out of the person wearing it... I thought bludgeoning seemed most appropriate.
Thanks for the help guys - I'll get this working yet!
konny666 Fri, 9th Apr '04, 7:13pm BigStick,
yup, recursive DelayCommands will also work fine. however, the CPU savings is negligible unless you're dealing with large multiplayer servers - i've profiled scripts written in both fashions. at any rate, i published a "Torches that burn out after some time" script to NWVault shortly after Hordes was released, using recursive delaycommands. logically, it's the most efficient method and so would appear to be the best choice from a programmer's point of view, but the heartbeat is still more intuitive for non-programmers, i think.
the problem is when you've got a big routine or loop running which takes up more than 0.1ms of script execution time... that's when the recursive delaycommand method becomes appealing.
Alavin,
consider applying *magical* damage instead of bludgeoning. this way, if the character has a "Belt of Bludgeoning Resistance" equipped, he won't be immune to the curse!
Alavin Fri, 9th Apr '04, 8:06pm Hmm, magic damage would be a better idea. Someone's belt shouldn't help them when they're being strangled...
BigStick Thu, 15th Apr '04, 1:39pm The DAMAGE_POWER_ENERGY option on the damage effect is supposed to get around any resistance that the character may have to the specified damage type, so you should be able to use whatever type seems right to you.
konny666 -
My biggest problem with using the heartbeat for this is that the character most likely won't be cursed with this problem for any significant fraction of the time that the module is running. If you force a check on every heartbeat for the entire time that the module is up, it's going to take more time than is needed. Without knowing what else is going on in the module, I'd hesitate to recommend the less efficient approach. If it were to be retricted to just one area I could see going that route, but the character could travel to any part of the module, if he survives long enough. The CPU savings may be negligible, but I almost always prefer the more efficient approach. Besides, I was writing this with the possibility in mind of using it in a mod of my own so wanted to keep it generic enough to fit a number of uses. :)
Alavin -
Long story short, either method will work and it's up to you to determine which way will work better for you and your module.
konny666 Thu, 15th Apr '04, 7:53pm yup BS, i agree with you, thats the method i use in my own stuff. ;) but i find the HB method is easier to explain to newbies - not implying that the OP was a newbie, but he *could* be. then once they've gotten the old HB method down-pat (remember, this new method was only possible post-SoU) they can upgrade to the better method. or not, if the HB method works fine and they're not terribly interested in becoming a scripting guru... which may be one of the biggest turn-offs about building NWN modules (1)
(1) that is, people with skill in fantasy writing or visual aesthetics (area design) tend to hate the programming aspect of it, which is basically C!
BigStick Fri, 16th Apr '04, 1:59pm Agreed! And those of us who actually enjoy the scripting parts of building (brushing off the old, mostly unused C skills) don't necessarily have the best writing and/or area design skills.
I hadn't realized that the recursive calls feature was not implemented until SoU, I figured that it was just one of the many things that I hadn't discovered earlier. ;)
It must be just me, but I find the heartbeat method more difficult to wrap my brain around. :o It seems intuitively obvious what will happen if a script tells the character to run a script every 6 seconds until a condition is met.
konny666 Sat, 17th Apr '04, 8:49am well it was only after SoU that the DelayCommand function became reliable. before SoU, it would tend to get nullified upon area transitions, save games, etc. pretty useless. thats why all the old scripts (2002-ish) used heartbeats for EVERYTHING. nowadays, everyone's switched to chained delaycommands. and the reason Bioware made Delaycommand more robust for SoU was 'coz they needed it to run all the fancy-schmancy cutscenes! (useless NWN trivia)
(BTW isnt it strange that while even the first InfinityEngine game had cutscene functionality it took BW a year to add it to the Aurora engine? i wonder what other IE "features" are still missing from Aurora...)
Anyways, I'm also more for scripting than actual building. however i must say that the release of the CEP might just spur me to actually build a complete mod - the CEP takes one "headache" out of the mod-building cycle (deciding on whether to use purely stock content or custom content, how much custom content, HAKpak size, combining hak's and 2da's, etc.) whether you love or hate the CEP, tons of people are downloading it... it's becoming standard.
|
|