//::////////////////////////////////////////////// //:: Conhort dynamic conversation //:: filename //::////////////////////////////////////////////// /** @file Dynamic conversation file for cohorts Handles all the normal cohort options plus: item useage feat useage spell useage interactions with nearby stuff Note: This is one of the few convos where the PC is not talking to themselves @author Primogenitor @date Created - 2006.07.12 */ //::////////////////////////////////////////////// //::////////////////////////////////////////////// #include "inc_dynconv" #include "prc_inc_leadersh" #include "x0_inc_henai" //#include "x0_i0_henchman" ////////////////////////////////////////////////// /* Constant defintions */ ////////////////////////////////////////////////// const int STAGE_ENTRY = 0; const int STAGE_REENTRY = 1; const int STAGE_SPELL = 100; const int STAGE_SPELL_TARGET = 101; const int STAGE_FEAT = 200; const int STAGE_FEAT_TARGET = 201; const int STAGE_ITEM = 300; const int STAGE_ITEM_SPELL = 301; const int STAGE_ITEM_TARGET = 302; const int STAGE_IDENTIFY = 400; const int STAGE_IDENTIFY_YES = 401; const int STAGE_IDENTIFY_NO = 402; const int STAGE_TACTICS = 500; const int STAGE_TACTICS_EQUIP = 501; const int STAGE_TACTICS_DEFEND = 502; const int STAGE_TACTICS_ATTACK = 503; const int STAGE_TACTICS_DISTANCE = 504; const int STAGE_TACTICS_DISTANCE_CLOSE = 541; const int STAGE_TACTICS_DISTANCE_MEDIUM = 542; const int STAGE_TACTICS_DISTANCE_LONG = 542; const int STAGE_TACTICS_LOCK_HELP = 505; const int STAGE_TACTICS_LOCK_NOHELP = 506; const int STAGE_TACTICS_STEALTH_ALWAYS = 507; const int STAGE_TACTICS_STEALTH_COMBAT = 507; const int STAGE_TACTICS_STEALTH_NEVER = 508; const int STAGE_LEAVE = 600; const int STAGE_LEAVE_YES = 601; const int STAGE_LEAVE_NO = 602; ////////////////////////////////////////////////// /* Aid functions */ ////////////////////////////////////////////////// void AddUseableFeats(int nMin, int nMax, object oPC, object oCohort) { int i; for(i=nMin;i abort return; if(nValue == DYNCONV_SETUP_STAGE) { // Check if this stage is marked as already set up // This stops list duplication when scrolling if(!GetIsStageSetUp(nStage, oPC)) { // variable named nStage determines the current conversation node // Function SetHeader to set the text displayed to the PC // Function AddChoice to add a response option for the PC. The responses are show in order added if(nStage == STAGE_ENTRY || nStage == STAGE_REENTRY) { if(oPC == GetMaster(oCohort)) { if(nStage == STAGE_ENTRY) SetHeader("What do you want?"); else if(nStage == STAGE_REENTRY) SetHeader("What do you *really* want?"); AddChoice("I need you to cast a spell", 1, oPC); AddChoice("I need you to use a feat", 2, oPC); AddChoice("I need you to use an item", 3, oPC); AddChoice("I need you to identify my equipment", 4, oPC); AddChoice("I need you to change your tactics", 5, oPC); AddChoice("I think we need to part ways", 6, oPC); } else { if(!GetIsObjectValid(GetMaster(oCohort))) if(DEBUG) DoDebug("Master not valid!"); if(!GetIsObjectValid(oCohort)) if(DEBUG) DoDebug("Cohort not valid!"); //speaker not their master SetHeader("Sorry, I can't talk to you right now. Ask "+GetName(GetMaster(oCohort))+" and see if they can help."); //no responces } //SetHeader("Foo."); //AddChoice("Bar", 1, oPC); //AddChoice("Baz!", 2, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //using spellss else if(nStage == STAGE_SPELL) { SetHeader("If I must. Which spell do you want me to cast?"); AddUseableSpells(0, 1000, oPC, oCohort); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //targetting spells is combined with feats //using feats else if(nStage == STAGE_FEAT) { SetHeader("If I must. Which feat do you want me to use?"); AddUseableFeats(0, 1000, oPC, oCohort); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_FEAT_TARGET || nStage == STAGE_SPELL_TARGET) { int nFeat = GetLocalInt(oCohort, "PRC_FeatToUse"); int nSpellID = StringToInt(Get2DACache("feat", "SPELLID", nFeat)); if(nFeat < 0) { //subradial feat nSpellID = 0-nFeat; nFeat = GetLocalInt(oCohort, "SubradialSpellFeatID"+IntToString(nSpellID)); } if(nStage == STAGE_SPELL_TARGET) nSpellID = GetLocalInt(oCohort, "PRC_SpellToUse"); int nTargetType = HexToInt(Get2DACache("spells", "TargetType", nSpellID)); int nHostileSpell = StringToInt(Get2DACache("spells", "HostileSetting", nSpellID)); string sRangeType = Get2DACache("spells", "Range", nSpellID); float fRange = 50.0; if(sRangeType == "S" || sRangeType == "T" || sRangeType == "P") fRange = 8.0; else if(sRangeType == "M") fRange = 20.0; else if(sRangeType == "L") fRange = 40.0; /* # 0x01 = 1 = Self # 0x02 = 2 = Creature # 0x04 = 4 = Area/Ground # 0x08 = 8 = Items # 0x10 = 16 = Doors # 0x20 = 32 = Placeables */ int nCaster = nTargetType & 1; int nCreature = nTargetType & 2; int nLocation = nTargetType & 4; int nItem = nTargetType & 8; int nDoor = nTargetType & 16; int nPlaceable = nTargetType & 32; int nCount; if(array_exists(oCohort, "PRC_ItemsToUse_Target")) array_delete(oCohort, "PRC_ItemsToUse_Target"); array_create(oCohort, "PRC_ItemsToUse_Target"); //self if(nCaster) { AddChoice("Self ("+GetName(oCohort)+")", array_get_size(oCohort, "PRC_ItemsToUse_Target")); array_set_object(oCohort, "PRC_ItemsToUse_Target", array_get_size(oCohort, "PRC_ItemsToUse_Target"), oCohort); } //nearby objects or locations of those objects if(nCreature || nDoor || nPlaceable || nLocation) { object oTest = GetFirstObjectInShape(SHAPE_SPHERE, fRange, GetLocation(oCohort)); while(GetIsObjectValid(oTest)) { int nType = GetObjectType(oTest); if(((nType == OBJECT_TYPE_CREATURE && nCreature) || (nType == OBJECT_TYPE_DOOR && nDoor) || (nType == OBJECT_TYPE_PLACEABLE && nPlaceable) || nLocation) && oTest != oCohort)//self-casting is covered earlier { AddChoice(GetName(oTest), array_get_size(oCohort, "PRC_ItemsToUse_Target")); array_set_object(oCohort, "PRC_ItemsToUse_Target", array_get_size(oCohort, "PRC_ItemsToUse_Target"), oTest); } oTest = GetNextObjectInShape(SHAPE_SPHERE, fRange, GetLocation(oCohort)); } } //items in inventory if(nItem) { object oTest = GetFirstItemInInventory(oCohort); while(GetIsObjectValid(oTest)) { AddChoice("(in inventory) "+GetName(oTest), array_get_size(oCohort, "PRC_ItemsToUse_Target")); array_set_object(oCohort, "PRC_ItemsToUse_Target", array_get_size(oCohort, "PRC_ItemsToUse_Target"), oTest); oTest = GetNextItemInInventory(oCohort); } } if(nStage == STAGE_FEAT_TARGET) { SetHeader("Who or what do you want me to use "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)))+" on?"); } else if(nStage == STAGE_SPELL_TARGET) SetHeader("Who or what do you want me to cast "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)))+" on?"); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //using items else if(nStage == STAGE_ITEM) { SetHeader("If I must. Which item do you want me to activate?"); if(!array_exists(oCohort, "PRC_ItemsToUse")) { array_create(oCohort, "PRC_ItemsToUse"); int nSlot; for(nSlot = 0; nSlot < 14; nSlot++) { object oItem = GetItemInSlot(nSlot, oCohort); if(GetIsObjectValid(oItem) && GetIdentified(oItem)) { AddChoice(GetName(oItem), array_get_size(oCohort, "PRC_ItemsToUse")); array_set_object(oCohort, "PRC_ItemsToUse", array_get_size(oCohort, "PRC_ItemsToUse"), oItem); } } object oItem = GetFirstItemInInventory(oCohort); while(GetIsObjectValid(oItem)) { if(GetIdentified(oItem)) { itemproperty ipTest = GetFirstItemProperty(oItem); itemproperty ipInvalid; while(GetIsItemPropertyValid(ipTest)) { if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL) { AddChoice(GetName(oItem), array_get_size(oCohort, "PRC_ItemsToUse")); array_set_object(oCohort, "PRC_ItemsToUse", array_get_size(oCohort, "PRC_ItemsToUse"), oItem); ipTest = ipInvalid; } else ipTest = GetNextItemProperty(oItem); } } oItem = GetNextItemInInventory(oCohort); } } else { int i; for(i=0;i= nGP) { SetIdentified(oItem, TRUE); sList += GetName(oItem)+"\n"; } } oItem = GetNextItemInInventory(oPC); } SetHeader(sList); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_IDENTIFY_NO) { SetHeader("Then why did you bother asking me if you didnt want me to have a look!"); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //tactics else if(nStage == STAGE_TACTICS) { SetHeader("*You* would advise *me* on tactics?"); AddChoice("I want to adjust your equipment.", 1, oPC); //x0_d2_hen_attck if(!GetAssociateState(NW_ASC_MODE_DEFEND_MASTER, oCohort)) AddChoice("Defend me and don't attack until I do.", 2, oPC); //x0_d2_hen_defnd if(GetAssociateState(NW_ASC_MODE_DEFEND_MASTER, oCohort)) AddChoice("Go ahead and attack as soon as you see enemies.", 3, oPC); AddChoice("I want to change the distance you stay away from me.", 4, oPC); //nw_ch_no_locks if(!GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oCohort)) AddChoice("Help me if I fail to open a locked door or chest.", 5, oPC); //nw_ch_yes_locks if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oCohort)) AddChoice("Don't help me if I fail to open a locked door or chest.", 6, oPC); //follows the HotU stealth system, as in xp2_hen_dae conversation AddChoice("Try to remain stealthy all the time.", 7, oPC); AddChoice("Stay stealthy, but only until the next fight.", 8, oPC); //x2_d1_instealth //if(GetActionMode(oCohort, ACTION_MODE_STEALTH)) //not used, cohort drops stealth during conversation AddChoice("Don't try to be stealthy anymore.", 9, oPC); AddChoice("I don't want to change anything else right now.", 10, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_TACTICS_EQUIP) { SetHeader("*sigh* Very well, then. Here is my equipment."); OpenInventory(oCohort, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_TACTICS_DEFEND || nStage == STAGE_TACTICS_ATTACK || nStage == STAGE_TACTICS_LOCK_HELP || nStage == STAGE_TACTICS_LOCK_NOHELP || nStage == STAGE_TACTICS_STEALTH_ALWAYS || nStage == STAGE_TACTICS_STEALTH_COMBAT || nStage == STAGE_TACTICS_STEALTH_NEVER || nStage == STAGE_TACTICS_DISTANCE_CLOSE || nStage == STAGE_TACTICS_DISTANCE_MEDIUM || nStage == STAGE_TACTICS_DISTANCE_LONG) { string sMessage; if(nStage == STAGE_TACTICS_DEFEND) sMessage = "Very well, then."; else if(nStage == STAGE_TACTICS_ATTACK) sMessage = "None will stand against us!"; else if(nStage == STAGE_TACTICS_LOCK_HELP) sMessage = "Indeed. Where you have failed, I shall succeed!"; else if(nStage == STAGE_TACTICS_LOCK_NOHELP) sMessage = "You can attempt them on your own then."; else if(nStage == STAGE_TACTICS_STEALTH_ALWAYS) sMessage = "Very well, I shall strike from the shadows whenever I am able."; else if(nStage == STAGE_TACTICS_STEALTH_COMBAT) sMessage = "I shall remain hidden until the battle begins, then I will burst forth to slaughter our foes."; else if(nStage == STAGE_TACTICS_STEALTH_NEVER) sMessage = "I do not like to hide in the shadows, anyway."; else if(nStage == STAGE_TACTICS_DISTANCE_CLOSE || nStage == STAGE_TACTICS_DISTANCE_MEDIUM || nStage == STAGE_TACTICS_DISTANCE_LONG) sMessage = "As you wish."; SetHeader(sMessage+" Do you want to change anything else?"); AddChoice("No, that is all.", 2, oPC); AddChoice("Yes.", 1, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_TACTICS_DISTANCE) { SetHeader("How far apart should we remain, then?"); AddChoice("Stay close.", 1, oPC); AddChoice("Keep a medium distance.", 2, oPC); AddChoice("Stay a long distance away.", 3, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //leaving the party else if(nStage == STAGE_LEAVE) { SetHeader("What?! You would turn me aside and make your way without me?"); AddChoice("Leave me. Now.", 1, oPC); AddChoice("Alright, fine. Stay with me, then.", 2, oPC); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_LEAVE_YES) { SetHeader("Bah! Leave if you will, but you shall not get far without me!"); DelayCommand(3.0, RemoveCohortFromPlayer(oCohort, oPC)); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } else if(nStage == STAGE_LEAVE_NO) { SetHeader("Ah, so you have not lost your mind completely."); MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values } //add more stages for more nodes with Else If clauses } // Do token setup SetupTokens(); } // End of conversation cleanup else if(nValue == DYNCONV_EXITED) { // Add any locals set through this conversation array_delete(oCohort, "PRC_ItemsToUse"); array_delete(oCohort, "PRC_ItemsToUse_Target"); DeleteLocalObject(oCohort, "PRC_ItemToUse"); DeleteLocalObject(oCohort, "PRC_ItemToUse_Spell"); DeleteLocalInt(oCohort, "PRC_FeatToUse"); DeleteLocalInt(oCohort, "PRC_SpellToUse"); DeleteLocalInt(oCohort, "PRC_InCohortConvoMarker"); } // Abort conversation cleanup. // NOTE: This section is only run when the conversation is aborted // while aborting is allowed. When it isn't, the dynconvo infrastructure // handles restoring the conversation in a transparent manner else if(nValue == DYNCONV_ABORTED) { // Add any locals set through this conversation array_delete(oCohort, "PRC_ItemsToUse"); array_delete(oCohort, "PRC_ItemsToUse_Target"); DeleteLocalObject(oCohort, "PRC_ItemToUse"); DeleteLocalObject(oCohort, "PRC_ItemToUse_Spell"); DeleteLocalInt(oCohort, "PRC_FeatToUse"); DeleteLocalInt(oCohort, "PRC_SpellToUse"); DeleteLocalInt(oCohort, "PRC_InCohortConvoMarker"); } // Handle PC responses else { // variable named nChoice is the value of the player's choice as stored when building the choice list // variable named nStage determines the current conversation node int nChoice = GetChoice(oPC); int nOldStage = nStage; if(nStage == STAGE_ENTRY || nStage == STAGE_REENTRY) { switch(nChoice) { case 1: nStage = STAGE_SPELL; break; case 2: nStage = STAGE_FEAT; break; case 3: nStage = STAGE_ITEM; break; case 4: nStage = STAGE_IDENTIFY; break; case 5: nStage = STAGE_TACTICS; break; case 6: nStage = STAGE_LEAVE; break; } } else if(nStage == STAGE_LEAVE) { switch(nChoice) { case 1: nStage = STAGE_LEAVE_YES; break; case 2: nStage = STAGE_LEAVE_NO; break; } } else if(nStage == STAGE_SPELL) { SetLocalInt(oCohort, "PRC_SpellToUse", nChoice); nStage = STAGE_SPELL_TARGET; } else if(nStage == STAGE_SPELL_TARGET) { int nSpellID = GetLocalInt(oCohort, "PRC_SpellToUse"); object oTarget = array_get_object(oCohort, "PRC_ItemsToUse_Target", nChoice); //test if location or object //use object by preference int nTargetType = HexToInt(Get2DACache("spells", "TargetType", nSpellID)); /* # 0x01 = 1 = Self # 0x02 = 2 = Creature # 0x04 = 4 = Area/Ground # 0x08 = 8 = Items # 0x10 = 16 = Doors # 0x20 = 32 = Placeables */ int nCaster = nTargetType & 1; int nCreature = nTargetType & 2; int nLocation = nTargetType & 4; int nItem = nTargetType & 8; int nDoor = nTargetType & 16; int nPlaceable = nTargetType & 32; int nType = GetObjectType(oTarget); if((oTarget == oCohort && nCaster) || (nType == OBJECT_TYPE_CREATURE && nCreature) || (nType == OBJECT_TYPE_DOOR && nDoor) || (nType == OBJECT_TYPE_PLACEABLE && nPlaceable) || (nType == OBJECT_TYPE_ITEM && nItem)) { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionCastSpellAtObject(nSpellID, oTarget)); } else if(nLocation) { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionCastSpellAtLocation(nSpellID, GetLocation(oTarget))); } AllowExit(DYNCONV_EXIT_FORCE_EXIT); } else if(nStage == STAGE_FEAT) { SetLocalInt(oCohort, "PRC_FeatToUse", nChoice); //a few hardcoded feats are fuggly if(nChoice == FEAT_ANIMAL_COMPANION) { DecrementRemainingFeatUses(oCohort, FEAT_ANIMAL_COMPANION); AssignCommand(oCohort, SummonAnimalCompanion()); AllowExit(DYNCONV_EXIT_FORCE_EXIT); } else if(nChoice == FEAT_SUMMON_FAMILIAR) { DecrementRemainingFeatUses(oCohort, FEAT_SUMMON_FAMILIAR); AssignCommand(oCohort, SummonFamiliar()); AllowExit(DYNCONV_EXIT_FORCE_EXIT); } //if its self only, use it if(StringToInt(Get2DACache("feat", "TARGETSELF", nChoice))) { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionUseFeat(nChoice, oCohort)); //feat used, end conversation AllowExit(DYNCONV_EXIT_FORCE_EXIT); } nStage = STAGE_FEAT_TARGET; } else if(nStage == STAGE_FEAT_TARGET) { int nFeat = GetLocalInt(oCohort, "PRC_FeatToUse"); object oTarget = array_get_object(oCohort, "PRC_ItemsToUse_Target", nChoice); if(nFeat < 0) { //subradial feat int nSpellID; nSpellID = 0-nFeat; nFeat = GetLocalInt(oCohort, "SubradialSpellFeatID"+IntToString(nSpellID)); DecrementRemainingFeatUses(oCohort, nFeat); AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionCastSpellAtObject(nSpellID, oTarget, METAMAGIC_ANY, TRUE)); } else { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionUseFeat(nFeat, oTarget)); } AllowExit(DYNCONV_EXIT_FORCE_EXIT); } else if(nStage == STAGE_ITEM) { object oItem = array_get_object(oCohort, "PRC_ItemsToUse", nChoice); SetLocalObject(oCohort, "PRC_ItemToUse", oItem); //if its multiple spells itemproperty ipTest = GetFirstItemProperty(oItem); int nSpellCount; while(GetIsItemPropertyValid(ipTest)) { if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL) nSpellCount++; ipTest = GetNextItemProperty(oItem); } if(nSpellCount > 1) { nStage = STAGE_ITEM_SPELL; } else { ipTest = GetFirstItemProperty(oItem); while(GetIsItemPropertyValid(ipTest)) { if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL) break; ipTest = GetNextItemProperty(oItem); } int nSpellID = GetItemPropertySubType(ipTest); //convert that to a real ID nSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", nSpellID)); //store it SetLocalInt(oCohort, "PRC_ItemToUse_Spell", nSpellID); nStage = STAGE_ITEM_TARGET; } } else if(nStage == STAGE_ITEM_SPELL) { SetLocalInt(oCohort, "PRC_ItemToUse_Spell", nChoice); //check if its self-only, if so use it object oItem = GetLocalObject(oCohort, "PRC_ItemToUse"); int nSpellID = GetLocalInt(oCohort, "PRC_ItemToUse_Spell"); object oTarget = array_get_object(oCohort, "PRC_ItemsToUse_Target", nChoice); itemproperty ipIP; ipIP = GetFirstItemProperty(oItem); while(GetIsItemPropertyValid(ipIP)) { if(GetItemPropertyType(ipIP) == ITEM_PROPERTY_CAST_SPELL) { int nipSpellID = GetItemPropertySubType(ipIP); //convert that to a real ID nipSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", nipSpellID)); if(nipSpellID == nSpellID) { if(DEBUG) DoDebug("Ending itemprop loop "+IntToString(nipSpellID)); break;//end while loop } } ipIP = GetNextItemProperty(oItem); } //test if location or object //use object by preference int nTargetType = HexToInt(Get2DACache("spells", "TargetType", nSpellID)); if(nTargetType == 1) { //self only item, use it AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionUseItemPropertyAtObject(oItem, ipIP, oCohort)); if(DEBUG) DoDebug("Running ActionUseItemPropertyAtObject() at "+GetName(oCohort)); //item used, end conversation AllowExit(DYNCONV_EXIT_FORCE_EXIT); } nStage = STAGE_ITEM_TARGET; } else if(nStage == STAGE_ITEM_TARGET) { object oItem = GetLocalObject(oCohort, "PRC_ItemToUse"); int nSpellID = GetLocalInt(oCohort, "PRC_ItemToUse_Spell"); object oTarget = array_get_object(oCohort, "PRC_ItemsToUse_Target", nChoice); itemproperty ipIP; ipIP = GetFirstItemProperty(oItem); while(GetIsItemPropertyValid(ipIP)) { if(GetItemPropertyType(ipIP) == ITEM_PROPERTY_CAST_SPELL) { int nipSpellID = GetItemPropertySubType(ipIP); //convert that to a real ID nipSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", nipSpellID)); if(nipSpellID == nSpellID) { if(DEBUG) DoDebug("Ending itemprop loop "+IntToString(nipSpellID)); break;//end while loop } } ipIP = GetNextItemProperty(oItem); } //test if location or object //use object by preference int nTargetType = HexToInt(Get2DACache("spells", "TargetType", nSpellID)); /* # 0x01 = 1 = Self # 0x02 = 2 = Creature # 0x04 = 4 = Area/Ground # 0x08 = 8 = Items # 0x10 = 16 = Doors # 0x20 = 32 = Placeables */ int nCaster = nTargetType & 1; int nCreature = nTargetType & 2; int nLocation = nTargetType & 4; int nItem = nTargetType & 8; int nDoor = nTargetType & 16; int nPlaceable = nTargetType & 32; int nType = GetObjectType(oTarget); if((oTarget == oCohort && nCaster) || (nType == OBJECT_TYPE_CREATURE && nCreature) || (nType == OBJECT_TYPE_DOOR && nDoor) || (nType == OBJECT_TYPE_PLACEABLE && nPlaceable) || (nType == OBJECT_TYPE_ITEM && nItem)) { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionUseItemPropertyAtObject(oItem, ipIP, oTarget)); if(DEBUG) DoDebug("Running ActionUseItemPropertyAtObject() at "+GetName(oTarget)); } else if(nLocation) { AssignCommand(oCohort, ClearAllActions()); AssignCommand(oCohort, ActionUseItemPropertyAtLocation(oItem, ipIP, GetLocation(oTarget))); if(DEBUG) DoDebug("Running ActionUseItemPropertyAtLocation() at "+GetName(oTarget)); } AllowExit(DYNCONV_EXIT_FORCE_EXIT); } else if(nStage == STAGE_IDENTIFY) { switch(nChoice) { case 1: nStage = STAGE_IDENTIFY_YES; break; case 2: nStage = STAGE_IDENTIFY_NO; break; } } else if(nStage == STAGE_TACTICS) { switch(nChoice) { case 1: nStage = STAGE_TACTICS_EQUIP; break; case 2: nStage = STAGE_TACTICS_DEFEND; SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, TRUE, oCohort); break; case 3: nStage = STAGE_TACTICS_ATTACK; SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE, oCohort); break; case 4: nStage = STAGE_TACTICS_DISTANCE; break; case 5: nStage = STAGE_TACTICS_LOCK_HELP; SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, TRUE, oCohort); break; case 6: nStage = STAGE_TACTICS_LOCK_NOHELP; SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, FALSE, oCohort); break; case 7: nStage = STAGE_TACTICS_STEALTH_ALWAYS; AssignCommand(oCohort, ClearAllActions()); SetLocalInt(oCohort, "X2_HENCH_STEALTH_MODE", 1); break; case 8: nStage = STAGE_TACTICS_STEALTH_COMBAT; AssignCommand(oCohort, ClearAllActions()); SetLocalInt(oCohort, "X2_HENCH_STEALTH_MODE", 2); break; case 9: nStage = STAGE_TACTICS_STEALTH_NEVER; AssignCommand(oCohort, ClearAllActions()); SetLocalInt(oCohort, "X2_HENCH_STEALTH_MODE", 0); SetActionMode(oCohort, ACTION_MODE_STEALTH, FALSE); break; case 10: nStage = STAGE_REENTRY; break; } } else if(nStage == STAGE_TACTICS_DISTANCE) { switch(nChoice) { case 1: nStage = STAGE_TACTICS_DISTANCE_CLOSE; //nw_ch_dist_6 SetAssociateState(NW_ASC_DISTANCE_2_METERS, TRUE, oCohort); SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE, oCohort); SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE, oCohort); break; case 2: nStage = STAGE_TACTICS_DISTANCE_MEDIUM; //nw_ch_dist_12 SetAssociateState(NW_ASC_DISTANCE_2_METERS, FALSE, oCohort); SetAssociateState(NW_ASC_DISTANCE_4_METERS, TRUE, oCohort); SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE, oCohort); break; case 3: nStage = STAGE_TACTICS_DISTANCE_LONG; //nw_ch_dist_18 SetAssociateState(NW_ASC_DISTANCE_2_METERS, FALSE, oCohort); SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE, oCohort); SetAssociateState(NW_ASC_DISTANCE_6_METERS, TRUE, oCohort); break; } } else if(nStage == STAGE_TACTICS_DEFEND || nStage == STAGE_TACTICS_ATTACK || nStage == STAGE_TACTICS_LOCK_HELP || nStage == STAGE_TACTICS_LOCK_NOHELP || nStage == STAGE_TACTICS_STEALTH_ALWAYS || nStage == STAGE_TACTICS_STEALTH_COMBAT || nStage == STAGE_TACTICS_STEALTH_NEVER || nStage == STAGE_TACTICS_DISTANCE_CLOSE || nStage == STAGE_TACTICS_DISTANCE_MEDIUM || nStage == STAGE_TACTICS_DISTANCE_LONG) { switch(nChoice) { case 1: nStage = STAGE_TACTICS; break; case 2: AllowExit(DYNCONV_EXIT_FORCE_EXIT); break; } } else if(nStage == STAGE_LEAVE) { switch(nChoice) { case 1: nStage = STAGE_LEAVE_YES; break; case 2: nStage = STAGE_LEAVE_NO; break; } } // Store the stage value. If it has been changed, this clears out the choices SetStage(nStage, oPC); //if stage changed, mark the new one as not set up if(nStage != nOldStage) MarkStageNotSetUp(nStage, oPC); } }