GhostOfGod wrote...
I've been a big advocate of tag-based scripting since it was implemented. However I've been doing some re-scripting in a test PW just trying to condense stuff. I decided to make 1 script for all placeable useable objects that just checks the tag and does that one part of the script for that object. That started me thinking about the old way of activating items by just sticking all the if (sTag == "blah blah") checks in one big OnActivate script. I'd like to get the opinion of people with PWs on whether the old or new "tag-based" method is less "computer resource" intesive etc. I'm thinking now just having less scripts would be the prefered method? I don't know. What do you guys prefer and why?
Some general remarks, first, which I will later contradict (food for thought, in other words):
Using tags is somewhat primitive - it only happened to begin with because you couldn't set locals in the toolset, at first. Use local variables, and save tags for GetByTag functions and other things of that nature - times when you need to indicate an instance varies in some way from its palette. I'm assuming locals are much faster than the string compares for tags, but that's not really the basis of my answer. The locals are designed to do precisely what you're using the tags for. You can change or add to them later without making a mess of things. Consider, for example, the first set of underwater areas I added to my mod, which required waterbreathing, had custom spellhooks, etc. I originally did a tag check, checking for a prefix. Of course, if I want another mod-wide subsystem like that, I can't use a prefix anymore, if I want to be able to have overlap. That's one reason we switched to an Area_Underwater variable - another being simple human readability.
All that being said, though, we use a combination tag-based system, only firing it for some events (most of our stuff is modwide). The one event we do use it for is onactivate. We break down activation scripts by area grouping (one for aboleths items, one for locathah, another for Mount Uroboros, etc). And yes, we use tag-based code for that. I would not attempt to consolidate ALL onactivates into one, as that kills most of the modularity that tag-based was intended to allow. A lot of it boils down into what makes your mod organized in a way you can understand it best.
We use prefixing of tags and resrefs to link them to an area, allowing us to find a given thing with relative speed, instead of paging through tens of thousands of lines of code in huge, unitary, and slower-to-run master scripts. If a script or palette item is prefixed aby_, I know it's related to our Abyss areas, while abo_ is aboleths, and so on. We also have a randuse script for our multi-area random loot with useable properties - again, it just depends on what makes sense to you.
Here's a sample script written this way - as you can see, it still has a lot of added functions and includes - another reason to go modular (avoiding cross-inclusion, even though Skywing's can handle circular includes, they're still a bit distasteful). Skip to the bottom to read the main() function first - the rest is irrelevant, other than to make the point about problems with unitary scripts:
#include "hg_inc"
#include "x2_inc_switches"
#include "ac_spell_inc"
#include "ac_dispel_inc"
#include "ac_itemreq_inc"
#include "inc_draw"
#include "fky_chat_inc"
#include "ac_cooldown_inc"
void ApplyTreeHealing (object oPC, object oTree, int nRounds) {
if (nRounds < 1 ||
!GetIsObjectValid(oPC) ||
!GetIsObjectValid(oTree) ||
GetArea(oPC) != GetArea(oTree)) {
SetPlotFlag(oTree, FALSE);
DestroyObject(oTree);
return;
}
DelayCommand(6.0, ApplyTreeHealing(oPC, oTree, nRounds - 1));
location lTarget = GetLocation(oTree);
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_HUGE, lTarget);
effect eHeal = EffectLinkEffects(EffectVisualEffect(VFX_IMP_HEALING_S), EffectHeal(60));
while (GetIsObjectValid(oTarget)) {
if (GetFactionEqual(oTarget, oPC) || GetLocalInt(oTarget, "AllowHeal"))
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_HUGE, lTarget);
}
}
void ApplyDeath (object oTarget) {
if (GetIsDead(oTarget)) {
ApplyVisualAtLocation(VFX_IMP_DEATH_L, GetLocation(oTarget));
return;
}
SetPlotFlag(oTarget, FALSE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDeath()), oTarget);
DelayCommand(0.1, ApplyDeath(oTarget));
}
void ApplyResurrection (object oTarget, object oPC) {
if (!GetIsObjectValid(oTarget) || !GetIsDead(oTarget))
return;
effect eRez = EffectResurrection();
effect eHeal = EffectHeal(GetMaxHitPoints(oTarget) + 10);
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_RESURRECTION, FALSE));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eRez, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
ApplyVisualAtLocation(VFX_IMP_RAISE_DEAD, GetLocation(oTarget));
SendMessageToParty(oTarget, C_MED_GREY + GetName(oPC) + " resurrects " + GetName(oTarget) + " : Potion of Life Unbound : *success*" + C_END);
AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
}
void UseAccusingStatue (object oPC, object oItem) {
location lTarget = GetLocation(oPC);
DelayCommand(0.0, DrawSpring(DURATION_TYPE_INSTANT, VFX_IMP_HEAD_EVIL, lTarget,
-3.0, 3.0, 0.0, 0.0, 0.0, 30, 0.0, 1.5, 0.0));
DelayCommand(1.0, DrawSpring(DURATION_TYPE_INSTANT, VFX_IMP_HEAD_EVIL, lTarget,
-3.0, 3.0, 0.0, 0.0, 0.0, 30, 0.0, 1.5, 180.0));
ApplyVisualToObject(GAOVFX_IMP_REDUCE_ABILITY_SCORE_YELLOW, oPC);
effect eLink = EffectImmunity(IMMUNITY_TYPE_CRITICAL_HIT);
eLink = EffectLinkEffects(eLink, EffectDamageImmunityDecrease(DAMAGE_TYPE_BLUDGEONING, 30));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityDecrease(DAMAGE_TYPE_PIERCING, 30));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityDecrease(DAMAGE_TYPE_SLASHING, 30));
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_IOUNSTONE_YELLOW));
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE));
eLink = ExtraordinaryEffect(eLink);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, TurnsToSeconds(2));
}
void UseBiorevivifier (object oPC, object oItem) {
int nTimer = GetCooldownTimer(oPC, "BIO");
if (nTimer > 0) {
FloatingTextStringOnCreature("You cannot use a biorejuvenator again for another " +
IntToString(nTimer) + " second" + (nTimer == 1 ? "" : "s") + "!", oPC, FALSE);
return;
}
DoRest(oPC, TRUE);
DestroyObject(oItem);
}
void UseCasterLevelBoost (object oPC, object oItem) {
int nUptime = GetLocalInt(GetModule(), "uptime");
int nIndex = 1;
int nUntil = GetLocalInt(oPC, "TempCasterLevel_1");
int nCheck = GetLocalInt(oPC, "TempCasterLevel_2");
if (nCheck < nUntil) {
nIndex = 2;
nUntil = nCheck;
}
nCheck = GetLocalInt(oPC, "TempCasterLevel_3");
if (nCheck < nUntil)
nIndex = 3;
ApplyVisualToObject(GAOVFX_IMP_IMPROVE_ABILITY_SCORE_PURPLE, oPC);
SetLocalInt(oPC, "TempCasterLevel_" + IntToString(nIndex), nUptime + 60);
}
void UseForcecage (object oPC, object oItem) {
if (GetItemCharges(oItem) < 1)
DestroyObject(oItem);
object oTarget = GetItemActivatedTarget();
if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE &&
GetIsTarget(oTarget, TARGET_TYPE_ENEMY, oPC) &&
GetChallengeRating(oTarget) <= 200.0 &&
!GetLocalInt(oTarget, "PCDeathAcc")) {
effect eLink = EffectVisualEffect(VFX_DUR_GLYPH_OF_WARDING);
eLink = EffectLinkEffects(eLink, EffectCutsceneImmobilize());
eLink = ExtraordinaryEffect(eLink);
SignalEvent(oTarget, EventSpellCastAt(oPC, SPELL_HOLD_MONSTER));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(1));
} else
FloatingTextStringOnCreature("You cannot use the Moderately Escapable Forcecage on " + GetName(oTarget) + "!", oPC, FALSE);
}
void UseMalleksLecture (object oPC, object oItem) {
/* temporary immunity to mords/breach, but no spellcasting capabilities;
* can only be used on self or pets */
}
void UsePixieBomb (object oPC, object oItem) {
/* summon several pixies for a short time */
}
void UsePotionOfTheThirdEye (object oPC, object oItem) {
object oArea = GetArea(oPC);
if (GetTag(oArea) != "limbohell") {
FloatingTextStringOnCreature("You can only use the Potion of the Third Eye in Limbo!", oPC, FALSE);
return;
}
int nCount = 1;
effect eVis = EffectVisualEffect(VFX_DUR_GHOSTLY_PULSE_QUICK);
object oWall = GetNearestObjectByTag("invisiblebarrier", oPC, nCount++);
while (GetIsObjectValid(oWall)) {
RemoveEffectsOfType(EFFECT_TYPE_VISUALEFFECT, oWall);
DelayCommand(nCount * 0.01, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eVis, oWall));
oWall = GetNearestObjectByTag("invisiblebarrier", oPC, nCount++);
}
AssignCommand(oArea, DelayCommand(300.0, DeleteLocalInt(oArea, "VisualsApplied")));
}
void UseResurrectionPotion (object oPC, object oItem) {
float fRadius = RADIUS_SIZE_MEDIUM;
if (GetRacialType(oPC) == RACIAL_TYPE_DRAGON) {
fRadius = RADIUS_SIZE_HUGE;
ApplyVisualToObject(VFX_FNF_LOS_HOLY_20, oPC);
} else
ApplyVisualToObject(VFX_FNF_LOS_HOLY_10, oPC);
location lTarget = GetLocation(oPC);
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lTarget);
while (GetIsObjectValid(oTarget)) {
if (GetIsPC(oTarget) && GetIsDead(oTarget) && GetFactionEqual(oTarget, oPC))
DelayCommand(GetDistanceBetween(oTarget, oPC) / 20, ApplyResurrection(oTarget, oPC));
oTarget = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lTarget);
}
}
void UseScrollOfTheMiser (object oPC, object oItem) {
object oTarget = GetItemActivatedTarget();
if (GetLocalString(oTarget, "ServerDestroyed") == "RESPAWN") {
FloatingTextStringOnCreature("You cannot restore items lost to death with the Scroll of the Miser!", oPC, FALSE);
return;
}
if (GetTag(oTarget) != "pileofrust" || GetItemPossessor(oTarget) != oPC) {
FloatingTextStringOnCreature("You can only restore your own slagged items with the Scroll of the Miser!", oPC, FALSE);
return;
}
if (GetGold(oPC) < 50000000) {
FloatingTextStringOnCreature("You must have 50 million gold to restore an item with Scroll of the Miser!", oPC, FALSE);
return;
}
ApplyVisualToObject(VFX_IMP_KNOCK, oPC);
TakeGoldFromCreature(50000000, oPC, TRUE);
ExecuteScript("repair_item", oTarget);
DestroyObject(oItem);
}
void UseSeedsOfLife (object oPC, object oItem) {
location lTarget = GetItemActivatedTargetLocation();
object oTree = CreateObject(OBJECT_TYPE_PLACEABLE, "randuse_lifetree", lTarget);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectCutsceneGhost()), oTree);
AssignCommand(GetArea(oPC), ApplyTreeHealing(oPC, oTree, 30));
DestroyObject(oItem);
}
void UseSpellFocusBoost (object oPC, object oItem, int nSchool) {
if (GetItemCharges(oItem) < 1)
DestroyObject(oItem);
int nVis;
switch (nSchool) {
case SPELL_SCHOOL_ABJURATION: nVis = VFX_IMP_HEAD_SONIC; break;
case SPELL_SCHOOL_CONJURATION: nVis = VFX_IMP_HEAD_ACID; break;
case SPELL_SCHOOL_DIVINATION: nVis = VFX_IMP_HEAD_NATURE; break;
case SPELL_SCHOOL_ENCHANTMENT: nVis = VFX_IMP_HEAD_COLD; break;
case SPELL_SCHOOL_EVOCATION: nVis = VFX_IMP_HEAD_FIRE; break;
case SPELL_SCHOOL_ILLUSION: nVis = VFX_IMP_HEAD_MIND; break;
case SPELL_SCHOOL_NECROMANCY: nVis = VFX_IMP_HEAD_EVIL; break;
case SPELL_SCHOOL_TRANSMUTATION: nVis = VFX_IMP_HEAD_ODD; break;
}
ApplyVisualToObject(nVis, oPC);
SetLocalInt(oPC, "TempSpellFocus_School", nSchool);
SetLocalInt(oPC, "TempSpellFocus_Until", GetLocalInt(GetModule(), "uptime") + 60);
effect eVis = ExtraordinaryEffect(EffectVisualEffect(VFX_DUR_IOUNSTONE_YELLOW));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oPC, 60.0);
}
void UseTulipofTenacity (object oPC, object oItem) {
int nXP = 210000 - GetXP(oPC);
if (nXP < 100000)
nXP = 100000;
GiveXPToCreature(oPC, nXP);
SetPlotFlag(oItem, FALSE);
DestroyObject(oItem);
}
void UseJewelOfMask (object oPC, object oItem) {
object oTarget = GetItemActivatedTarget();
if (GetTag(oTarget) != "hgt_maker") {
FloatingTextStringOnCreature("You can only upgrade Trap Makers with the Jewel of Mask!", oPC, FALSE);
return;
}
int nLimit = GetLocalInt(oTarget, "TrapMaker_Limit");
if (nLimit < 6) {
FloatingTextStringOnCreature("That trap maker is too weak to be upgraded with the Jewel of Mask!", oPC, FALSE);
return;
} else if (nLimit >= {
FloatingTextStringOnCreature("That trap maker is too powerful to be upgraded with the Jewel of Mask!", oPC, FALSE);
return;
}
SetPlotFlag(oItem, FALSE);
DestroyObject(oItem);
SetItemCursedFlag(oTarget, TRUE);
SetLocalInt(oTarget, "TrapMaker_Limit", nLimit + 1);
ApplyVisualToObject(VFX_IMP_HEAD_EVIL, oPC);
FloatingTextStringOnCreature("Your " + GetName(oTarget) + " has been upgraded to produce " +
(nLimit == 7 ? "Godlike" : "Legendary") + " traps!", oPC, FALSE);
}
void DoRandomWeapon (object oPC, object oItem) {
if (GetLocalInt(oItem, "Modified")) {
FloatingTextStringOnCreature("This weapon has already been randomized!", oPC, FALSE);
return;
}
int i, nEle = 5, nExo = 4;
string sEle = "6 7 9 10 13 ", sExo = "5 8 11 12 ", sType;
SetLocalInt(oItem, "Modified", 1);
sType = GetStringSubString(sEle, Random(5));
itemproperty ip = ItemPropertyDamageBonus(StringToInt(sType), IP_CONST_DAMAGEBONUS_5d12);
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oItem);
sType = GetStringSubString(sExo, Random(4));
itemproperty ipb = ItemPropertyDamageBonus(StringToInt(sType), IP_CONST_DAMAGEBONUS_5d12);
AddItemProperty(DURATION_TYPE_PERMANENT, ipb, oItem);
DrawSpring(DURATION_TYPE_INSTANT, VFX_IMP_CHARM, GetLocation(oPC), 2.5, 2.5, 2.0, 2.0, 0.0, 30, 1.0, 0.0);
}
void UseJumpItem(object oPC, object oItem) {
object oWay = GetWaypointByTag(GetLocalString(oItem, "JumpTo"));
location lJump = GetLocation(oWay);
object oArea = GetAreaFromLocation(lJump);
if (GetIsObjectValid(oArea)) {
AssignCommand(oArea, ForceJump(oPC, lJump));
} else
FloatingTextStringOnCreature("Invalid destination! Please alert a DM!", oPC, FALSE);
}
void ApplyImmunity (object oTarget, int nRounds) {
effect eLink = EffectImmunity(IMMUNITY_TYPE_CRITICAL_HIT);
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_IOUNSTONE_YELLOW));
eLink = ExtraordinaryEffect(eLink);
SetEffectSpellId(eLink, HGEFFECT_TEMP_CRITICAL_IMMUNITY);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nRounds));
}
void ApplyDispelImmunity (object oTarget, int nRounds) {
effect eLink = EffectSpellImmunity(SPELL_LESSER_DISPEL);
eLink = EffectLinkEffects(eLink, EffectSpellImmunity(SPELL_DISPEL_MAGIC));
eLink = EffectLinkEffects(eLink, EffectSpellImmunity(SPELL_GREATER_DISPELLING));
eLink = EffectLinkEffects(eLink, EffectVisualEffect(HGVFX_DUR_IOUNSTONE_VIBRANT_PURPLE));
eLink = ExtraordinaryEffect(eLink);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nRounds));
}
void DoMassDomination(object oPC) {
object oParty, oTarget;
int nCount, nCheck, i;
for (oParty = GetFirstFactionMember(oPC); GetIsObjectValid(oParty); oParty = GetNextFactionMember(oPC)) {
if (GetIsPC(oPC))
nCount++;
}
effect eDom = EffectLinkEffects(EffectDominated(), EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DOMINATED));
for (oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oPC, i++, CREATURE_TYPE_IS_ALIVE, TRUE);
GetIsObjectValid(oTarget);
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oPC, i++, CREATURE_TYPE_IS_ALIVE, TRUE)) {
if (GetIsImmune(oTarget, IMMUNITY_TYPE_MIND_SPELLS) || GetIsImmune(oTarget, IMMUNITY_TYPE_DOMINATE))
continue;
if (GetHasEffectOfType(EFFECT_TYPE_DOMINATED, oTarget))
continue;
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDom, oTarget, RoundsToSeconds(20));
nCheck++;
if (nCheck >= nCount)
break;
}
}
void main () {
if (GetUserDefinedItemEventNumber() != X2_ITEM_EVENT_ACTIVATE)
return;
SetExecutedScriptReturnValue(X2_EXECUTE_SCRIPT_END);
object oPC = GetItemActivator();
object oItem = GetItemActivated();
string sRes = GetResRef(oItem);
if (!GetItemIsUsable(oItem, oPC))
return;
int nId = StringToInt(GetStringRight(GetResRef(oItem), 3));
if (GetStringLeft(sRes, 6) == "randwp") {
if ((nId > 499) && (nId < 550))
DoRandomWeapon(oPC, oItem);
else
FloatingTextStringOnCreature("This weapon is bugged! Please report this error to a DM.", oPC, FALSE);
return;
}
/* Add 1000 to id if non-useable; for random loot with coded special powers */
if (GetStringLeft(sRes, 7) != "randuse")
nId += 1000;
/* XXX: convert Scroll of Intervention to Remove Paralysis (remove HGEFFECT_PHYSICAL_DOMINATION) */
switch (nId) {
case 1: AssignCommand(oPC, UseCasterLevelBoost(oPC, oItem)); break;
case 2: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_ABJURATION)); break;
case 3: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_CONJURATION)); break;
case 4: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_DIVINATION)); break;
case 5: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_ENCHANTMENT)); break;
case 6: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_EVOCATION)); break;
case 7: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_ILLUSION)); break;
case 8: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_NECROMANCY)); break;
case 9: AssignCommand(oPC, UseSpellFocusBoost(oPC, oItem, SPELL_SCHOOL_TRANSMUTATION)); break;
case 10: AssignCommand(oPC, UseBiorevivifier(oPC, oItem)); break;
case 26: AssignCommand(oPC, UseResurrectionPotion(oPC, oItem)); break;
case 28: AssignCommand(oPC, UseMalleksLecture(oPC, oItem)); break;
case 29: AssignCommand(oPC, UseForcecage(oPC, oItem)); break;
case 34: AssignCommand(oPC, UsePotionOfTheThirdEye(oPC, oItem)); break;
case 35: AssignCommand(oPC, UseScrollOfTheMiser(oPC, oItem)); break;
case 37: AssignCommand(oPC, UseSeedsOfLife(oPC, oItem)); break;
case 39: AssignCommand(oPC, UsePixieBomb(oPC, oItem)); break;
case 41: AssignCommand(oPC, UseAccusingStatue(oPC, oItem)); break;
case 42: AssignCommand(oPC, UseTulipofTenacity(oPC, oItem)); break;
case 45: AssignCommand(oPC, UseJewelOfMask(oPC, oItem)); break;
case 47: AssignCommand(oPC, UseJumpItem(oPC, oItem)); break;
case 1119: AssignCommand(oPC, DoMassDomination(oPC)); break; /* randam119 */
case 1132: AssignCommand(oItem, ApplyImmunity(oPC, 50)); break; /* randbl132 */
case 1146: AssignCommand(oItem, ApplyImmunity(oPC, 15)); break; /* randbl146 */
}
}
That said, we also have nwnx_events-based code, which allows for 'fast-use' items, spells, etc - code which cancels the event and executes in its place. For that, we use variables, though some of them point right back to the item's tag with a 'use tag' variable. For some idea what that looks like:
case EVENT_TYPE_USE_ITEM:
oItem = GetEventItem();
if (GetLocalInt(oItem, "FKY_CHAT_INSTANT")) {
oTarget = GetEventTarget();
if (GetObjectType(oTarget) == OBJECT_TYPE_TRIGGER)
lTarget = GetLocation(OBJECT_SELF);
else
lTarget = Location(GetArea(OBJECT_SELF), GetEventPosition(), GetFacing(OBJECT_SELF));
if (DoInstantUse(OBJECT_SELF, oItem, oTarget, lTarget))
BypassEvent();
}
break;
[/quote]
And DoInstantUse (taken from the linux version of SIMTools):
[code]
int DoInstantUse(object oIUPC, object oIUItem, object oIUTarget, location lIUTarget)
{
string sTag = GetTag(oIUItem);
string sScript = GetLocalString(oIUItem, "FKY_CHAT_INSTANT_SCRIPT");
if (sTag == "fky_chat_ventril")
return DoVentril(oIUPC, oIUItem, oIUTarget, lIUTarget);
else if (sTag == "fky_chat_target")
return DoTarget(oIUPC, oIUItem, oIUTarget, lIUTarget);
else if (sScript != "") {
if (sScript == "TAG")
sScript = sTag;
SetLocalObject(oIUPC, "FKY_CHAT_INSTANT_ITEM", oIUItem);
SetLocalObject(oIUPC, "FKY_CHAT_INSTANT_TARGET", oIUTarget);
SetLocalLocation(oIUPC, "FKY_CHAT_INSTANT_LOCATION", lIUTarget);
ExecuteScript(sScript, oIUPC);
DeleteLocalObject(oIUPC, "FKY_CHAT_INSTANT_ITEM");
DeleteLocalObject(oIUPC, "FKY_CHAT_INSTANT_TARGET");
DeleteLocalLocation(oIUPC, "FKY_CHAT_INSTANT_LOCATION");
return TRUE;
}
/* BEGIN HG SPECIFIC */
else if (GetStringLowerCase(sTag) == "pclist")
return DoPCList(oIUPC, oIUItem, oIUTarget, lIUTarget);
else if (GetLocalInt(oIUItem, "PseudoSpell") && GetLocalInt(oIUItem, "Singleton"))
return DoPseudoSpell(oIUPC, oIUItem, oIUTarget, lIUTarget);
/* END HG SPECIFIC */
return FALSE;
}
My second question has to do with the NESS spawn system. So for those who are using it or who have used it in the past, is it better to go with the area HB method or the OnEnter psuedo HB method?
I don't use NESS. My general rule probably applies, though, setting other considerations like bugginess aside. We use pseudos whenever they'll be running a 5th of mod uptime or less, since they are roughly 5 times as cpu-intensive as an equivalent heartbeat. Of course, there may be idiosyncratic reasons to use pseudos with NSS that I'm unaware of (or not to).
Funky
Modifié par FunkySwerve, 19 avril 2013 - 04:02 .