Highv Priest wrote...
Ok as a standard scripter for a couple years, I have to ask... What's the difference between using ExecuteScript and using an in-script block of code?
For example...
ExecuteScript("blah", OBJECT_SELF);
Blah = void main(){ AssignCommand(OBJECT_SELF, SpeakString("Blah"));}
OR
void Blah(object oSelf)
{
AssignCommand(oSelf, SpeakString("Blah"));
}
The only difference I see is that executescript is an absolute waste... Instead of simply using 1 script to handle things, you're using at minimum.. 2(and using mathematical logic, I have to assume that the computer having to only use 1 script file is cheaper then the computer having to use 2). It'd be great if executescript would transfer ownership of the script to the person it's being executed on(especially since it gives them the title of OBJECT_SELF), but it doesn't.
Does ExecuteScript do anything useful?
All kinds of things. To transfer ownership, just AssignCommand the execution.
That aside, however, it's incredibly useful for flexibiity and flow control, and can save you a lot of duplicative scripting. In our generic modwide area entry script, for example, if we want to do area-specific things, we just ES them based on a variable set on the area:
/* execute specific onenter script if specified */
string sScript = GetLocalString(oArea, "Area_OnEnter");
if (sScript != "")
ExecuteScript(sScript, oArea);
Likewise, our dynamic convo scriptset would not be possible without it:
#include "hg_inc"
#include "ac_dynconv_inc"
int StartingConditional () {
object oPC = GetPCSpeaker();
int i, nMax = GetLocalInt(oPC, "DynConv_Filter_Max");
for (i = 0; i < nMax; i++)
DeleteLocalInt(oPC, "DynConv_Filter_" + IntToString(i));
DeleteLocalInt(oPC, "DynConv_Filter_Max");
string sScript = GetLocalString(oPC, "DynConv_Script");
if (sScript == "")
return FALSE;
if (GetLocalInt(oPC, "DynConv_End")) {
DeleteLocalInt(oPC, "DynConv_End");
return FALSE;
}
/* execute script callbacks as needed */
if (GetLocalInt(oPC, "DynConv_Stage") == DYNCONV_STAGE_INIT)
ExecuteScript(sScript, oPC);
SetLocalInt(oPC, "DynConv_Stage", DYNCONV_STAGE_MENU);
ExecuteScript(sScript, oPC);
Ditto our encounter system:
void EncExecuteScripts (object oTrig, object oArea, string sType) {
struct SubString ss;
ss.rest = GetLocalString(oArea, "Enc" + sType + "Scripts");
string sScripts = GetLocalString(oTrig, "Enc" + sType + "Scripts");
if (ss.rest != "" && sScripts != "")
ss.rest += " ";
ss.rest += sScripts;
while (ss.rest != "") {
ss = GetFirstSubString(ss.rest);
ExecuteScript(ss.first, oTrig);
}
}
Our trap system:
void TrapExecuteScripts (object oTrig, object oArea, string sType) {
struct SubString ss;
ss.rest = GetLocalString(oArea, "Trap" + sType + "Scripts");
string sScripts = GetLocalString(oTrig, "Trap" + sType + "Scripts");
if (ss.rest != "" && sScripts != "")
ss.rest += " ";
ss.rest += sScripts;
while (ss.rest != "") {
ss = GetFirstSubString(ss.rest);
ExecuteScript(ss.first, oTrig);
}
}
It's also very useful for avoiding tangling includes, or for executing blocks of code you call a lot from different places - that is, it assists in modularity. We use it to call up our 'resurrection' event, for example, from all sorts of different scripts:
afx_deathcrown (23): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (117): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (206): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (295): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (323): AssignCommand(oJump, ExecuteScript("fky_deathprocess", oJump));
afx_deathcrown (354): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (374): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (395): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (420): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
afx_deathcrown (436): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
ca_clr_massrez (32): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
es_miracle (28): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
ev_lifetransrod (34): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
fky_chat_dm_comm (1123): AssignCommand(oDMTarget, ExecuteScript("fky_deathprocess", oDMTarget));//this includes dar, which is problematic because of crossincluding with hgll and chat
guildcontestport (48): AssignCommand(oGuilder, ExecuteScript("fky_deathprocess", oGuilder));
hell_amodeus_dth (32): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
hg_inc (3899): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
hg_inc (3936): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
hg_respawn (245): AssignCommand(oArea, ExecuteScript("fky_deathprocess", oPC));
nw_s0_raisdead (119): AssignCommand(si.target, ExecuteScript("fky_deathprocess", si.target));
nw_s2_bardsong (204): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
paragon_spell (1424): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
randuse (65): AssignCommand(oTarget, ExecuteScript("fky_deathprocess", oTarget));
voyageskip (159): AssignCommand(oPC, ExecuteScript("fky_deathprocess", oPC));
Likewise, instead of rewriting a dozen different variations on the same code, you can generalize it, and make the similar code modular, to accept the variations. By way of example, we gave our Red Dragon Disciples a fear aura. Rather than rewriting all the special aura code we have to ensure that auras fire (they're normally very low priority), we simply route that ability through existing code:
ca_rdd_fearaura (27): AssignCommand(oPC, ExecuteScript("nw_s1_aurafear", oPC));
Likewise, our gnomish inventors use bombs that emulate spell effects:
x2_s3_bomb (61): if (GetTag(oItem) == "gi_it_bombs") { /* Gnomish Inventor Bombs - these rely on GetSpellInfo not firing until they ExecuteScript */
x2_s3_bomb (68): case GI_BOMB_CUSSER: ExecuteScript("x2_s2_cursesong", OBJECT_SELF); return;
x2_s3_bomb (69): case GI_BOMB_EASER: ExecuteScript("nw_s2_bardsong", OBJECT_SELF); return;
x2_s3_bomb (70): case GI_BOMB_BLOWER: ExecuteScript("x0_s0_gustwind", OBJECT_SELF); return;
x2_s3_bomb (71): case GI_BOMB_STICKER: ExecuteScript("x2_s0_stnehold", OBJECT_SELF); return;
x2_s3_bomb (72): case GI_BOMB_GREASER: ExecuteScript("nw_s0_grease", OBJECT_SELF); return;
x2_s3_bomb (73): case GI_BOMB_TEASER: ExecuteScript("x0_s0_laugh", OBJECT_SELF); return;
x2_s3_bomb (74): case GI_BOMB_MELTER: ExecuteScript("nw_s0_acidfog", OBJECT_SELF); return;
x2_s3_bomb (75): case GI_BOMB_RUMBLER: ExecuteScript("hgs_gen_sphere", OBJECT_SELF); return;
x2_s3_bomb (76): case GI_BOMB_NETTER: ExecuteScript("nw_s0_entangle", OBJECT_SELF); return;
x2_s3_bomb (77): case GI_BOMB_CRACKER: ExecuteScript("x2_s0_grtthdclp", OBJECT_SELF); return;
x2_s3_bomb (78): case GI_BOMB_SHOCKER: ExecuteScript("hgs_gen_sphere", OBJECT_SELF); return;
x2_s3_bomb (80): case GI_BOMB_CLAPPER: ExecuteScript("x2_s0_grtthdclp", OBJECT_SELF); return;
x2_s3_bomb (81): case GI_BOMB_SMOKER: ExecuteScript("qc_gi_smoker_aoe", OBJECT_SELF); return;
x2_s3_bomb (82): case GI_BOMB_WARPER: ExecuteScript("nw_s0_timestop", OBJECT_SELF); return;
x2_s3_bomb (83): case GI_BOMB_CRUNCHER: ExecuteScript("nw_s0_implosion", OBJECT_SELF); return;
x2_s3_bomb (84): case GI_BOMB_FUMER: ExecuteScript("nw_s0_wailbansh", OBJECT_SELF); return;
I could go on, and on, and on. It is one of THE MOST useful functions out there.
Funky