// Here are the spectators. You can have as many spectators as you like, // just add them here, and refer to them in the feedback for each trick object oPerem = GetObjectByTag ("PEREM"); object oSpectator1 = GetObjectByTag ("BOY"); object oSpectator2 = GetObjectByTag ("CONVICT"); object oSpectator3 = GetObjectByTag ("WOMAN"); object oSpectator4 = GetObjectByTag ("PATRON"); object oTarget = GetObjectByTag ("SpellPoint"); // Name of the tag of the chicken blueprint we will create from // string sChickenTemplate = "PEREM_CHICKEN"; // The delay, in seconds between text spoken by wizard and audience float iSecsDelay = 1.5; int chooseATrick () { // Choose a trick to perform. Roll a number between 1 and 100. // Note that these probabilities can be changed as desired, and // the number of tricks can be changed as desired. Just make sure // there is a State number in the "switch" statement in the main program // for each trick number generated here. int iTrick; // Used to keep track of the last trick done int iLastTrick = GetLocalInt (OBJECT_SELF, "LAST_TRICK"); int bDifferentTrick = FALSE; // Always make sure that the trick we come up with is *never* the same as the last one while (!bDifferentTrick) { int iRoll = d100 (); if (iRoll < 20) iTrick = 1; // Trick 1 else if (iRoll < 40) iTrick = 2; // Trick 2 else if (iRoll < 65) iTrick = 3; // Trick 3 else if (iRoll < 80) iTrick = 4; // Trick 4 else if (iRoll < 95) iTrick = 5; // Trick 5 else iTrick = 6; // Trick 6 (5% chance!) // Check if the trick is different from the last one we did bDifferentTrick = (iTrick != iLastTrick); } // Remember the last one we used SetLocalInt (OBJECT_SELF, "LAST_TRICK", iTrick); return iTrick; } void makeRandomIntroductoryComments () { // The Wizard introduces the next trick int iRoll = d100 (); if (iRoll < 20) { ActionSpeakString ("I shall now demonstrate a little cantrip my grandmother taught me when I was a lad"); ActionWait (iSecsDelay); } else if (iRoll < 40) { ActionSpeakString ("Now where did I put that lizard tail?"); ActionWait (iSecsDelay); ActionSpeakString ("Here it is. Prepare to be enthralled!"); ActionWait (iSecsDelay); } else if (iRoll < 60) { ActionSpeakString ("I need some quiet for this next one"); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("I saw this great trick, the other day..."))); ActionWait (iSecsDelay); ActionSpeakString ("Quiet I say!"); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Oh! Sorry"))); ActionWait (iSecsDelay); ActionSpeakString ("Prepare to be amazed!"); ActionWait (iSecsDelay); } else if (iRoll < 80) { ActionSpeakString ("You'll like this cantrip, I'm sure"); ActionWait (iSecsDelay); } else { ActionSpeakString ("You won't see just anyone doing this next one"); ActionWait (iSecsDelay); } } void makeRandomInitialComment () { // Sometimes the audience will make an initial comment, before the trick starts int iRoll = d100 (); if (iRoll < 5) { ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("This better be good"))); ActionWait (iSecsDelay); } else if (iRoll < 10) { ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("I'm hungry"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Be quiet, now"))); ActionWait (iSecsDelay); } else if (iRoll < 15) { ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Yawn!!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("Waiting..."))); ActionWait (iSecsDelay); } else if (iRoll < 20) { ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Hmmm"))); ActionWait (iSecsDelay); } else if (iRoll < 25) { ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("You say something?"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Shut up and watch"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("Shhhhh"))); ActionWait (iSecsDelay); } else if (iRoll < 30) { ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("I'm bored"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("Me too."))); ActionWait (iSecsDelay); } else { // No initial comment, this time } } void makeRandomFinalComment () { // Sometimes the audience will always make a final comment after the trick int iRoll = d100 (); if (iRoll < 20) { ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Not bad"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("It was ok"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("I missed it, do it again..."))); } else if (iRoll < 40) { ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Ooooo!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Ok, I suppose"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("Nice!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("Huh?"))); } else if (iRoll < 60) { ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Ho hum"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("Nice!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Wow!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("That was ok.."))); } else if (iRoll < 80) { ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("Impressive!"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator4, ActionSpeakString ("Very nice.."))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Ooh I liked that one!"))); } else { ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Wow! Can you show me how to do that?"))); ActionWait (iSecsDelay); ActionSpeakString ("Certainly not. Do NOT try this at home"); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator1, ActionSpeakString ("Oh ... all right then"))); ActionWait (iSecsDelay); ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("Ha ha!"))); ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Hee hee!"))); ActionWait (iSecsDelay); } } void castSpell (int iSpellType, int iVisualEffectType) { // The wizard waves his arms, casts a "fake" spell, and a visual effect // is shown as well effect eVfx; // Cast a fake spell // ActionCastFakeSpellAtObject (iSpellType, OBJECT_SELF); ActionCastFakeSpellAtObject (iSpellType, oTarget); //Create the new visual effect, then apply it eVfx = EffectVisualEffect (iVisualEffectType); ActionDoCommand (ApplyEffectToObject (DURATION_TYPE_INSTANT, eVfx, OBJECT_SELF)); } void polymorphIntoChicken () { // Create a chicken. // This function returns "void", so it can be used as an argument to ActionDoCommand effect eEffect = EffectPolymorph(POLYMORPH_TYPE_CHICKEN); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, OBJECT_SELF, 10.0f); } // ************************************************************************ // ************************************************************************ void main() { // User-defined event fired for the Wizard // Retrieve the current state value int iState = GetLocalInt (OBJECT_SELF, "STATE"); // Have an event so we can artificially fire a heartbeat if needed event evHeartbeat = EventUserDefined (1001); int iTrick; // Get the event int nUser = GetUserDefinedEventNumber(); if (nUser == 1004) // 1004 == OnDialogue { // A conversation with a PC is about to start, so stop what we're doing ClearAllActions (); // Set our state to idle, so we don't interrupt the conversation SetLocalInt (OBJECT_SELF, "STATE", 0); // Set the counter to something high, so when we resume the tricks, // we start casting spells immediately SetLocalInt (OBJECT_SELF, "HEARTBEAT_COUNT", 99); } else if (nUser == 1001) // 1001 == heartbeat { // A heartbeat has occurred ! int iHeartbeatCount = GetLocalInt (OBJECT_SELF, "HEARTBEAT_COUNT"); iHeartbeatCount++; // Only do something every few heartbeats, not every time if (iHeartbeatCount > 2) { // We do want to do something this time around // Reset the counter so we start counting again until the next time iHeartbeatCount = 0; // figure out what we should do now switch (iState) { case 0: // Idle state // Nothing to do break; case 90: // Start performing tricks // Choose a trick to perform iTrick = chooseATrick (); // Set our state to the trick number to perform SetLocalInt (OBJECT_SELF, "STATE", iTrick); // Make sure we do it first time around iHeartbeatCount = 99; // Fire a heartbeat event, so we start the new trick *now* SignalEvent (OBJECT_SELF, evHeartbeat); break; case 1: // Perform Trick 1 ClearAllActions (); // Say a few words first makeRandomIntroductoryComments (); // Sometimes the audience will make an initial comment makeRandomInitialComment (); // Cast the spell castSpell (POLYMORPH_TYPE_RED_DRAGON, VFX_FNF_STRIKE_HOLY); // Get random reaction from audience makeRandomFinalComment (); // Set our state to choose the next trick SetLocalInt (OBJECT_SELF, "STATE", 90); break; case 2: // Perform Trick 2 ClearAllActions (); // Say a few words first makeRandomIntroductoryComments (); // Sometimes the audience will make an initial comment makeRandomInitialComment (); // Cast the spell castSpell (SPELL_BLADE_BARRIER, VFX_FNF_PWKILL); // Get random reaction from audience makeRandomFinalComment (); // Set our state to choose the next trick SetLocalInt (OBJECT_SELF, "STATE", 90); break; case 3: // Perform Trick 3 ClearAllActions (); // Say a few words first makeRandomIntroductoryComments (); // NO random audience comments before this one ;) // Cast the spell castSpell (SPELL_CALL_LIGHTNING, VFX_FNF_IMPLOSION); // Get random reaction from audience makeRandomFinalComment (); // Set our state to choose the next trick SetLocalInt (OBJECT_SELF, "STATE", 90); break; case 4: // Perform Trick 4 ClearAllActions (); // Say a few words first makeRandomIntroductoryComments (); // Sometimes the audience will make an initial comment makeRandomInitialComment (); // Cast the spell castSpell (SPELL_CLARITY, VFX_IMP_FROST_L); // Get random reaction from audience makeRandomFinalComment (); // Set our state to choose the next trick SetLocalInt (OBJECT_SELF, "STATE", 90); break; case 5: // Perform Trick 5 ClearAllActions (); // Say a few words first ActionSpeakString ("And now for one of my favorites"); ActionWait (iSecsDelay); // Sometimes the audience will make an initial comment makeRandomInitialComment (); // Cast the spell castSpell (SPELL_DIVINE_POWER, VFX_FNF_GAS_EXPLOSION_FIRE); // Get random reaction from audience makeRandomFinalComment (); // Set our state to choose the next trick SetLocalInt (OBJECT_SELF, "STATE", 90); break; case 6: // Perform Trick 6 (The chicken trick !!) ClearAllActions (); // Say a few words first ActionSpeakString ("A difficult one this time"); ActionWait (iSecsDelay); // Sometimes the audience will make an initial comment makeRandomInitialComment (); // Cast the spell castSpell (SPELL_ELEMENTAL_SWARM, VFX_IMP_POLYMORPH); // Get reaction from audience // Pass control over to the first spectator AssignCommand (oSpectator1, ActionWait (4.0)); AssignCommand (oSpectator1, ActionSpeakString ("Wow!")); AssignCommand (oSpectator1, ActionWait (iSecsDelay)); AssignCommand (oSpectator1, ActionDoCommand (AssignCommand (oSpectator2, ActionSpeakString ("What???")))); AssignCommand (oSpectator1, ActionWait (iSecsDelay)); AssignCommand (oSpectator1, ActionDoCommand (AssignCommand (oSpectator3, ActionSpeakString ("Where did he go?!?!")))); AssignCommand (oSpectator1, ActionWait (iSecsDelay)); AssignCommand (OBJECT_SELF, ActionDoCommand (AssignCommand (OBJECT_SELF, ActionSpeakString ("What the cluck?")))); // Now polymorph Perem into a chicken ActionDoCommand (polymorphIntoChicken ()); // Set our state to idle, to wait until we are destroyed !! SetLocalInt (OBJECT_SELF, "STATE", 0); // Wait until a few funny comments from the chicken then turn // him back and start the spellcasting again... DelayCommand(10.0, SetLocalInt (OBJECT_SELF, "STATE", 90)); break; } // switch } // End of Heartbeat actions // Store the Heartbeat counter for next time SetLocalInt (OBJECT_SELF, "HEARTBEAT_COUNT", iHeartbeatCount); } // heartbeat event }