ࡱ> @`abcdefghijklmnopqrstuvwxyz{|}~ @ o[bjbjFF ,,8]T"""&B"G"L##,j" l"( m" m" m"m"q"q"t#######$#RG#\#i#m"m"### m" m"#P#P#P##Jh m" m"#P###P#P#P# m"j" LT"X|#N^P###0#P####P#tJ#P#ir"d$͖"P#˰""wNir"ir"ir"##|.D&$:#|.&Table of contents  TOC \o "1-3" \p " " \h \z \u  HYPERLINK \l "_Toc159540233" Table of contents  PAGEREF _Toc159540233 \h i  HYPERLINK \l "_Toc159540234" Global Action  PAGEREF _Toc159540234 \h 1  HYPERLINK \l "_Toc159540235" Global Artificial Intellegence  PAGEREF _Toc159540235 \h 249  HYPERLINK \l "_Toc159540236" Global Being (Creature)  PAGEREF _Toc159540236 \h 299  HYPERLINK \l "_Toc159540237" Global Conditional  PAGEREF _Toc159540237 \h 415  HYPERLINK \l "_Toc159540238" Global Door  PAGEREF _Toc159540238 \h 487  HYPERLINK \l "_Toc159540239" Global Dungeon Master  PAGEREF _Toc159540239 \h 488  HYPERLINK \l "_Toc159540240" Global Group  PAGEREF _Toc159540240 \h 499  HYPERLINK \l "_Toc159540241" Global Include  PAGEREF _Toc159540241 \h 504  HYPERLINK \l "_Toc159540242" Global Placeables  PAGEREF _Toc159540242 \h 794  HYPERLINK \l "_Toc159540243" Global Reports  PAGEREF _Toc159540243 \h 811  HYPERLINK \l "_Toc159540244" Global Trigger  PAGEREF _Toc159540244 \h 858  HYPERLINK \l "_Toc159540245" Graphical User Interace  PAGEREF _Toc159540245 \h 862  HYPERLINK \l "_Toc159540246" Apendix  PAGEREF _Toc159540246 \h 900  NWN2 Stock scripts VOL I Main Scripts presented by Gamemaster x & The knights of the charred table  HYPERLINK "http://www.kalifornica.com" www.kalifornica.com kalifornica@gmail.com Foreword Hi, Gamemaster X here. I was peeking up the games skirt and looking at all its private parts and it occurred to me it would be nice to have all the stock scripts in an e-book format. What you have here is VOL 1 of a three part series of Neverwinter Nights 2 Stock scripts (the ones that install with the game). VOL 1 concentrates on Main Scripts or those scripts not specific to spells or a specific area. My intention is for the final series to be laid out as follows. VOL I Main Scripts VOL II Spell Scripts VOl III Area Scripts Vol IV 2da Global Action // ga_alignment /* This changes the player's alignment nActType = From a scale from +3 (Saintly/Paragon) to -3 (Fiendish/Anarchic), how much the act affects alignment bLawChaosAxis = 0 means adjust Good/Evil axis, 1 means adjust Law/Chaos axis */ // FAB 10/5 // EPF 6/6/05 chose different variable name for second parameter // ChazM 4/3/06 - Added conversion functions to maintain the functionality of this script, calibrated to the 101 point scale being used. // DBR 4/13/6 - Adjustment was being converted as if it was a final value instead of a delta. // DBR 4/18/6 - forgot to adjust for good/lawful as well. // ChazM 5/3/06 - complete rewrite - simplified to no longer be context sensitive to current alignment. // ChazM 5/3/06 - changed adjustment for 1-point acts, added "incarnate" acts // EPF 7/10/06 - added debug strings for balance testing // EPF 7/20/06 - dampened adjustment values for 1-3. Previous values made it too difficult to // remain neutral, which makes it just about impossible to play a druid. // ChazM 8/31/06 - Changed debug display to values instead of alignment constants; removed old commented code #include "ginc_debug" const int ACT_EVIL_INCARNATE = -4; const int ACT_EVIL_FIENDISH = -3; const int ACT_EVIL_MALEVOLENT = -2; const int ACT_EVIL_IMPISH = -1; const int ACT_GOOD_KINDLY = 1; const int ACT_GOOD_BENEVOLENT = 2; const int ACT_GOOD_SAINTLY = 3; const int ACT_GOOD_INCARNATE = 4; const int ACT_CHAOTIC_INCARNATE = -4; const int ACT_CHAOTIC_ANARCHIC = -3; const int ACT_CHAOTIC_FEY = -2; const int ACT_CHAOTIC_WILD = -1; const int ACT_LAWFUL_HONEST = 1; const int ACT_LAWFUL_ORDERLY = 2; const int ACT_LAWFUL_PARAGON = 3; const int ACT_LAWFUL_INCARNATE = 4; // Adjust Alignment notes: // Alignment is not treated as a continuous scale running from 0 to 100, but in three bands running from 0 to 30, 31 to 69 and 70 to 100. // Whenever a call to AdjustAlignment takes you over one of these boundaries, // your characters alignment is automatically placed at the middle of the new band, ie 15, 50 or 85. int LawChaosAxisAdjustment(object oPC, int iLawChaosActType) { int iAdjustment = 0; switch ( iLawChaosActType ) { case ACT_CHAOTIC_INCARNATE: iAdjustment = -70; break; case ACT_CHAOTIC_ANARCHIC: iAdjustment = -10; break; case ACT_CHAOTIC_FEY: iAdjustment = -3; break; case ACT_CHAOTIC_WILD: iAdjustment = -1; break; case 0: // Neutral acts not currently tracked iAdjustment = 0; break; case ACT_LAWFUL_HONEST: iAdjustment = 1; break; case ACT_LAWFUL_ORDERLY: iAdjustment = 3; break; case ACT_LAWFUL_PARAGON: iAdjustment = 10; break; case ACT_LAWFUL_INCARNATE: iAdjustment = 70; break; } if (iAdjustment > 0) AdjustAlignment(oPC, ALIGNMENT_LAWFUL, iAdjustment); else AdjustAlignment(oPC, ALIGNMENT_CHAOTIC, -iAdjustment); return (iAdjustment); } int GoodEvilAxisAdjustment(object oPC, int iGoodEvilActType) { int iAdjustment = 0; switch ( iGoodEvilActType ) { case ACT_EVIL_INCARNATE: iAdjustment = -70; break; case ACT_EVIL_FIENDISH: iAdjustment = -10; break; case ACT_EVIL_MALEVOLENT: iAdjustment = -3; break; case ACT_EVIL_IMPISH: iAdjustment = -1; break; case 0: // Neutral acts not currently tracked iAdjustment = 0; break; case ACT_GOOD_KINDLY: iAdjustment = 1; break; case ACT_GOOD_BENEVOLENT: iAdjustment = 3; break; case ACT_GOOD_SAINTLY: iAdjustment = 10; break; case ACT_GOOD_INCARNATE: iAdjustment = 70; break; } if (iAdjustment > 0) AdjustAlignment(oPC, ALIGNMENT_GOOD, iAdjustment); else AdjustAlignment(oPC, ALIGNMENT_EVIL, -iAdjustment); return (iAdjustment); } void main(int iActType, int bLawChaosAxis) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); int nAdjustment; if (bLawChaosAxis == 0) { nAdjustment = GoodEvilAxisAdjustment(oPC, iActType); PrettyMessage("Alignment shifted on Good-Evil Axis by " + IntToString(nAdjustment)); PrettyMessage("Overall Alignment on this axis = " + IntToString(GetGoodEvilValue(oPC))); } else { nAdjustment = LawChaosAxisAdjustment(oPC, iActType); PrettyMessage("Alignment shifted on Law-Chaos Axis by " + IntToString(nAdjustment)); PrettyMessage("Overall Alignment on this axis = " + IntToString(GetLawChaosValue(oPC))); } } // ga_attack /* This script makes the sAttacker attack the PC. It should be placed on an [END DIALOG] node. Parameters: string sAttacker = Tag of attacker whom will attack the PC. Default is OWNER. */ // FAB 10/7 // ChazM 4/26 #include "ginc_param_const" #include "ginc_actions" void main(string sAttacker) { object oAttacker = GetTarget(sAttacker, TARGET_OWNER); object oTarget = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); StandardAttack(oAttacker, oTarget); } // ga_attack_target /* This script makes the sAttacker attack the sTarget. It should be placed on an [END DIALOG] node. Parameters: string sAttacker = Tag of attacker. Default is OWNER. string sTarget = Tag of Target. Default is PC. */ // FAB 10/7 // ChazM 4/26 #include "ginc_param_const" #include "ginc_actions" void main(string sAttacker, string sTarget) { object oAttacker = GetTarget(sAttacker, TARGET_OWNER); object oTarget = GetTarget(sTarget, TARGET_PC); StandardAttack(oAttacker, oTarget); } // ga_blackout // // wrapper function for FadeToBlackParty() to instantly make screen black. Useful for the // first node of conversations. // CGaw & BMa 2/13/06 - Created. #include "ginc_cutscene" void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); FadeToBlackParty(oPC, 1, 0.0); } // ga_camera_facing_point_party /* Point the cameras of all PCs' in the Speaker's party to target sTarget. Camera will be fDistance meters away from the PC, and pitched at fPitch degrees. -fDistance can be between 1 and 25. At least 5 is advisable in most cases. 0 = use distance of current camera value -fPitch can be between 1 and 89. 89 is nearly parallel to the ground. 1 is almost directly overhead. 60-70 is usually a reasonable default. 0 = use pitch of current camera value - nTransitionType can be 0 or between 1 and 100. The higher the number, the faster the transition. 0 = snap to new facing, no transition. */ // EPF 9/14/06 // ChazM 9/15/06 - added defaults for current cam, moved funcs to ginc_cutscene #include "ginc_param_const" #include "x0_i0_position" #include "ginc_cutscene" #include "ginc_math" void main(string sTarget, float fDistance, float fPitch, int nTransitionType) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if(!GetIsObjectValid(oPC)) { return; //if there's no PC speaker, there's no point in setting the cam anyway. } // SetCameraFacing() uses -1.0 to use current camera default, we'll use 0.0 as well. if (IsFloatNearInt(fDistance, 0)) fDistance = -1.0f; if (IsFloatNearInt(fPitch, 0)) fPitch = -1.0f; object oTarget = GetTarget(sTarget); if(GetIsObjectValid(oTarget)) { SetCameraFacingPointParty(oPC, oTarget, fDistance, fPitch, nTransitionType); } } // ga_clear_comp() /* Removes all roster members from the PC party. Removed roster members are not despawned. */ // BMA-OEI 7/20/05 // EPF 1/9/06 -- added RemoveAllCompanions call. // TDE 3/23/06 -- Replaced entire script with DespawnAllCompanions. // BMA-OEI 5/23/06 -- replaced w/ RemoveRosterMembersFromParty(), updated comment #include "ginc_companion" void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); RemoveRosterMembersFromParty(oPC, FALSE, FALSE); } //ga_commandable /* Set's target's commandable state. 0 = action stack can not be modified 1 = action stack can be modified */ //ChazM 6/28/06 #include "ginc_param_const" void main(string sTarget, int iCommandable) { object oTarget = GetTarget(sTarget); AssignCommand(oTarget, SetCommandable(iCommandable)); int iCommandable = GetCommandable(oTarget); PrettyDebug(GetName(oTarget) + " commandable state is " + IntToString(iCommandable)); } // ga_compshift /* This is the companion shift script that adjusts a companion's reaction to the PC nCompanion = This is the integer value of the companion in question nChange = This is the amount their reaction is adjusted nOverride = If this isn't equal to 0, the companions reaction is set to this amount. Use with caution. */ // FAB 10/4 void main(int nGP, int nAllPCs) { /* This is a temp script - a real script will be added later nCompanion 1: Khelgar nChange -3: Strong negative change -2: Medium negative change -1: Small negative change +1: Small positive change +2: Medium positive change +3: Strong positive change */ } // ga_conversation_self /* start a conversation file with yourself. Parameters: string sConversation = Conversation file to start. */ // ChazM 2/25/06 // #include "ginc_param_const" void main(string sConversation) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); AssignCommand(oPC, ActionStartConversation(oPC, sConversation, TRUE, FALSE)); } // ga_create_obj(string sObjectType, string sTemplate, string sLocationTag, int bUseAppearAnimation, string sNewTag, float fDelay) /* Wrapper for CreateObject() with optional delay. Parameters: string sObjectType = Object type. The following are allowed: C - CREATURE P - PLACEABLE I - ITEM W - WAYPOINT S - STORE string sTemplate = Name of the template to create. string sLocationTag = Tag of the waypoint at which to create the object. int bUseAppearAnimation = If =1, object will use appear animation. string sNewTag = Optional new tag for created object. float fDelay = Delay, in seconds, before creating the object. */ // TDE 3/9/05 // ChazM 3/11/05 // BMA-OEI 1/11/06 removed default params #include "ginc_param_const" #include "ginc_actions" void main(string sObjectType, string sTemplate, string sLocationTag, int bUseAppearAnimation, string sNewTag, float fDelay) { object oLocation = GetObjectByTag(sLocationTag); location lLocation = GetLocation(oLocation); int iObjType = GetObjectTypes(sObjectType); DelayCommand(fDelay, ActionCreateObject(iObjType, sTemplate, lLocation, bUseAppearAnimation, sNewTag)); } // ga_cutscene_move // // Move and delay the advancing of the conversation for a maximum of nMilliseconds. // Conversation will also advance if the move completes. // "" for sMoverTag -> OBJECT_SELF #include "ginc_misc" void main(string sWPTag, int nMilliseconds, int bRun, string sMoverTag) { object oTarget; if(sMoverTag == "") { oTarget = OBJECT_SELF; } else { oTarget = GetTarget(sMoverTag); } ActionPauseCutscene(nMilliseconds); AssignCutsceneActionToObject(oTarget, ActionMoveToObject(GetTarget(sWPTag), bRun)); } // ga_date_advance /* Advance date by amount indicated nYear - Number of years to advance. nMonth - Number of months to advance. nDay - Number of days to advance. */ // ChazM 6/27/06 void main(int nYear, int nMonth, int nDay) { nYear = GetCalendarYear() + nYear; nMonth = GetCalendarMonth() + nMonth; nDay = GetCalendarDay() + nDay; // Set the new date SetCalendar(nYear, nMonth, nDay); } // ga_date_set /* Advance date by amount indicated nYear - Specific year to set calendar to from 1340 to 32001. nMonth - Specific month to set calendar from 1 to 12. nDay - Specific day to set calendar to from 1 to 28. */ // ChazM 6/27/06 void main(int nYear, int nMonth, int nDay) { // Set the new date SetCalendar(nYear, nMonth, nDay); } // ga_death /* This script makes objects appear dead sTag = The tag(s) of the object(s) to make dead. You can pass multiple tags, seperated by commas (NO SPACES) to make multiple objects dead (ie. "Object1,Object2,Object3") iInstance = The instance of the object(s) to make dead. Pass -1 to make all instances dead. */ // TDE 3/7/05 // BMA-OEI 1/11/06 removed default param // TDE 8/3/06 - Set Immortal and Plot flags to FALSE, Added some debug strings // TDE 8/28/06 - Changed SetIsDestroyable to (FALSE, FALSE, TRUE) so that the corpses can be looted #include "ginc_debug" void Death(string sTagString, int iInstance = 0) { PrettyDebug("Applying Death Effect To: " + sTagString + " Instance = " + IntToString(iInstance)); if (iInstance == -1) { int iInst; object oObject; while (GetIsObjectValid(GetObjectByTag(sTagString, iInst))) { oObject = GetObjectByTag(sTagString, iInst); AssignCommand(oObject, SetIsDestroyable( FALSE,FALSE,TRUE )); SetImmortal( oObject, FALSE ); SetPlotFlag( oObject, FALSE ); effect eFX = EffectDeath(); PrettyDebug("Name of oObject = " + GetName(oObject)); ApplyEffectToObject( DURATION_TYPE_INSTANT,eFX,oObject ); iInst ++; } } else { object oObject = GetObjectByTag(sTagString, iInstance); AssignCommand(oObject, SetIsDestroyable( FALSE,FALSE,TRUE )); SetImmortal( oObject, FALSE ); SetPlotFlag( oObject, FALSE ); effect eFX = EffectDeath(); PrettyDebug("Name of oObject = " + GetName(oObject)); ApplyEffectToObject( DURATION_TYPE_INSTANT,eFX,oObject ); } } void main(string sTagString, int iInstance) { string newString = sTagString; int iLen = GetStringLength(sTagString); //find first comma int CommaPos = FindSubString( newString, "," ); while(CommaPos != -1) { string tempString = GetSubString(newString, 0, CommaPos); Death(tempString, iInstance); newString = GetSubString(newString, CommaPos + 1, iLen); iLen = GetStringLength(newString); CommaPos = FindSubString( newString, "," ); } //newString is equal to last tag to destroy Death(newString, iInstance); } // ga_destroy /* This script destroys objects sTag = The tag(s) of the object(s) to destroy. You can pass multiple tags, seperated by commas (NO SPACES) to destroy multiple objects (ie. "Object1,Object2,Object3") NOTE: There may eventually be a function to eat white space (See Mantis 3296), but for now do not put spaces in the string. iInstance = The instance of the object to destroy. Pass -1 to destroy all instances. Pass 0 to destroy the first instance. fDelay = The delay before destroying the object(s) */ // TDE 3/7/05 // ChazM 3/8/05 - commented and tweaked. // ChazM 6/7/05 - fixed bug, modified comment // BMA-OEI 1/11/06 removed default param // detroy all objects (iInstance=-1) or a specific instance of object void Destroy(string sTagString, int iInstance = 0, float fDelay = 0.0) { if (iInstance == -1) { // delete all objects int iInst = 0; object oObject = GetObjectByTag(sTagString, iInst); while (GetIsObjectValid(oObject)) { DestroyObject (oObject, fDelay); iInst ++; oObject = GetObjectByTag(sTagString, iInst); } } else { // delete a specific instance of object DestroyObject (GetObjectByTag(sTagString, iInstance), fDelay); } } void main(string sTagString, int iInstance, float fDelay) { string sNewString = sTagString; int iLen = GetStringLength(sTagString); int iCommaPos = FindSubString( sNewString, "," ); //find first comma while(iCommaPos != -1) { // get first tag and destroy it string sTempString = GetSubString(sNewString , 0, iCommaPos); Destroy(sTempString, iInstance, fDelay); // drop first tag and comma sNewString = GetSubString(sNewString, iCommaPos + 1, iLen); // determine new length iLen = GetStringLength(sNewString); // get next comma position (returns -1 if not found) iCommaPos = FindSubString(sNewString, "," ); } //sNewString is equal to last tag to destroy Destroy(sNewString, iInstance, fDelay); } // ga_destroy_item /* This takes an item from a player sItemTag = This is the string name of the item's tag nQuantity = The number of items to destroy. -1 is all of the Player's items of that tag. nPCFaction = Take from the whole PC faction */ // FAB 9/30 // DBR 8/10/6 #include "nw_i0_plot" void DestroyItems(object oTarget,string sItem,int nNumItems) { int nCount = 0; object oItem = GetFirstItemInInventory(oTarget); while (GetIsObjectValid(oItem) == TRUE && nCount < nNumItems) { if (GetTag(oItem) == sItem) { //ActionTakeItem(oItem,oTarget); DestroyObject(oItem,0.1f); nCount++; } oItem = GetNextItemInInventory(oTarget); } return; } void main(string sItemTag,int nQuantity,int bPCFaction) { int nTotalItem; object oPCF,oPC = (GetPCSpeaker()==OBJECT_INVALID?GetFirstPC():GetPCSpeaker()); object oItem; // Items in inventory if ( bPCFaction == 0 ) { if ( nQuantity < 0 ) // Destroy all instances of the item { nTotalItem = GetNumItems( oPC,sItemTag ); DestroyItems( oPC,sItemTag,nTotalItem ); } else { DestroyItems( oPC,sItemTag,nQuantity ); } } else // For multiple players { oPCF = GetFirstFactionMember(oPC,FALSE); while (( GetIsObjectValid(oPCF) )&&(nQuantity!=0)) { if ( nQuantity < 0 ) // Destroy all instances of the item { nTotalItem = GetNumItems( oPCF,sItemTag ); DestroyItems( oPCF,sItemTag,nTotalItem ); } else { nTotalItem = GetNumItems( oPCF,sItemTag ); nQuantity -= nTotalItem; if (nQuantity<0) { nTotalItem+=nQuantity; nQuantity=0; } DestroyItems( oPCF,sItemTag,nTotalItem ); } oPCF = GetNextFactionMember(oPC,FALSE); } } } // ga_destroy_party_henchmen /* Destroy all henchmen in the entire party */ // ChazM 12/5/05 // ChazM 1/26/05 - Bug fix // ChazM 3/8/06 - funcs moved to ginc_henchman #include "ginc_henchman" #include "ginc_debug" /* int GetNumHenchmen(object oMaster=OBJECT_SELF) { int i = 1; object oHenchman = GetHenchman(oMaster, i); while (GetIsObjectValid(oHenchman)) { i++; //PrettyDebug ("GetNumHenchmen() - found: " + GetName(oHenchman)); oHenchman = GetHenchman(oMaster, i); } i = i-1; //PrettyDebug ("GetNumHenchmen() - Total found = " + IntToString(i)); return (i); } // Destroy a henchman // Note: won't be destroyed if has been set as undestroyable void DestroyHenchman(object oHenchman) { //PrettyDebug ("Removing " + GetName(oHenchman)); RemoveHenchman(GetMaster(oHenchman), oHenchman); SetPlotFlag(oHenchman, FALSE); DestroyObject(oHenchman); } // Destroy all the henchmen of this master void DestroyAllHenchmen(object oMaster=OBJECT_SELF) { int i; object oHenchman; // destroy them backwards to avoid problems w/ removeing henchmen causing re-indexing int iNumHenchmen = GetNumHenchmen(oMaster); for (i = iNumHenchmen; i>=1; i--) { oHenchman = GetHenchman(oMaster, i); //PrettyDebug ("Removing " + GetName(oHenchman)); //RemoveHenchman(oMaster, oHenchman); //SetPlotFlag(oHenchman, FALSE); DelayCommand(0.5f, DestroyHenchman(oHenchman)); // delay destructions so we have time to iterate through party properly } } // Destroy every henchman in the entire party void DestroyAllHenchmenInParty(object oPartyMember) { object oFM = GetFirstFactionMember(oPartyMember, FALSE); while(GetIsObjectValid(oFM)) { //PrettyDebug ("Examining " + GetName(oFM) + " for henchmen."); DestroyAllHenchmen(oFM); oFM = GetNextFactionMember(oPartyMember, FALSE); } } */ void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); DestroyAllHenchmenInParty(oPC); } // ga_disable_scripts /* saves and clears the event handlers */ // ChazM 12/21/05 // #include "ginc_param_const" #include "ginc_event_handlers" void main(string sTarget) { object oTarget = GetTarget(sTarget); SaveEventHandlers(oTarget); ClearEventHandlers(oTarget); } // ga_donothing.nss /* Do nothing, really. */ // BMA-OEI 8/17/05 // BMA-OEI 1/11/06 removed default param #include "ginc_debug" void main(string sDebugMessage) { if (sDebugMessage == "") sDebugMessage = "this is a placeholder script"; PrettyMessage("ga_donothing: rly " + sDebugMessage); } // ga_door_close /* This closes a door sTag = The tag of the door to close nLock = Set to 1 if you want to lock the door after it closes */ // FAB 10/11 void main(string sTag, int nLock) { object oDoor = GetObjectByTag( sTag ); DelayCommand ( 0.1, AssignCommand( oDoor, ActionCloseDoor( oDoor ) ) ); if ( nLock == 1 ) SetLocked( oDoor, TRUE ); } // ga_door_open /* This opens a door sTag = The tag of the door to open */ // FAB 10/11 void main(string sTag) { object oDoor = GetObjectByTag( sTag ); SetLocked( oDoor, FALSE ); DelayCommand ( 0.1, AssignCommand( oDoor, ActionOpenDoor( oDoor ) ) ); } // ga_effect /* Does an effect on the specified target. This function takes 5 params: string sEffect - one of the below effects string sParams - comma delimited list of needed params string sDuration - I - Instant (default), P - Permanent, or T, - Temporary w/ specified duration ex: temporay 30 seconds would be "T,30.0f" int iVisualEffect - -1=no visual, 0 = standard visual, or supply your own from visualeffects.2da (will be applied as an instant) string sTarget - Uses the standard GetTarget() function - default is the PC Speaker *** Effects and Paramaters *** AbilityIncrease - nAbility , nModifyBy -- Abilities: Str=0, Dex=1, Con=2, Int=3, Wis=4, Cha=5 AbilityDecrease - nAbility, nModifyBy Blindness - no params Damage - nDamageAmount, nDamageType, nDamagePower -- Types: Bludgeon=1, acid=16, fire=256, etc.; Powers: Normal=0, PlusThree=3, etc. Death - no params Disease - nDiseaseType -- (0-16) see DISEASE_* constants in nwscript.nss Heal - nDamageToHeal Paralyze - no params Poison - nPoisonType -- (0-43) see POISON_* constants in nwscript.nss Raise - no params Visual - nVisualEffectId -- see visualeffects.2da for param options Example 1: This action script will heal the PC Speaker 100hp in a conversation ga_effect ("Heal", "100", "", 0, "") Example 2: This action script will permanently give the PC Speaker in a conversation increased strength (+2) ga_effect ("AbilityIncrease", "0,2", "P", 0, "") */ // ChazM 4/11/05 // ChazM 11/6/06 - fixed params to be 0 based instead of 1 based (Bug found by robertharris). // Added a few more effects, added support for linked duration visual effects, edited description. // ChazM 11/6/06 fixed some visual effects, other minor changes. #include "ginc_param_const" void DoEffect(string sEffect, string sParams, string sDuration, int iVisualEffect, object oTarget); void main(string sEffect, string sParams, string sDuration, int iVisualEffect, string sTarget) { object oTarget = GetTarget(sTarget, "$PC"); DoEffect(sEffect, sParams, sDuration, iVisualEffect, oTarget); } void DoEffect(string sEffect, string sParams, string sDuration, int iVisualEffect, object oTarget) { int iDurationType = GetDurationType(GetStringParam(sDuration, 0)); float fDuration = 0.0f; if (iDurationType == DURATION_TYPE_TEMPORARY) fDuration = GetFloatParam(sDuration, 1); sEffect = GetStringLowerCase(sEffect); effect eEffect; int iVis = 0; int iVisType = DURATION_TYPE_INSTANT; if(sEffect == "abilitydecrease"){ eEffect = EffectAbilityDecrease(GetIntParam(sParams, 0), GetIntParam(sParams, 1)); iVis = VFX_IMP_REDUCE_ABILITY_SCORE; } else if(sEffect == "abilityincrease"){ eEffect = EffectAbilityIncrease(GetIntParam(sParams, 0), GetIntParam(sParams, 1)); iVis = VFX_IMP_IMPROVE_ABILITY_SCORE; } else if(sEffect == "blindness"){ eEffect = EffectBlindness(); iVis = VFX_IMP_BLIND_DEAF_M ; } else if(sEffect == "damage"){ eEffect = EffectDamage(GetIntParam(sParams, 0), GetIntParam(sParams, 1), GetIntParam(sParams, 2)); // iVis should be based on type iVis = VFX_IMP_FLAME_M; } else if(sEffect == "death"){ eEffect = EffectDeath(); iVis = VFX_IMP_DISEASE_S; } else if(sEffect == "disease"){ eEffect = EffectDisease(GetIntParam(sParams, 0)); iVis = VFX_IMP_DEATH; } else if(sEffect == "haste"){ eEffect = EffectHaste(); iVis = VFX_IMP_HASTE; } else if(sEffect == "heal"){ eEffect = EffectHeal(GetIntParam(sParams, 0)); iVis = VFX_IMP_HEALING_G; } else if(sEffect == "paralyze"){ eEffect = EffectParalyze(); iVisType = DURATION_TYPE_TEMPORARY; iVis = VFX_DUR_PARALYZED; } else if(sEffect == "poison"){ eEffect = EffectPoison(GetIntParam(sParams, 0)); iVis = VFX_IMP_POISON_L; } else if((sEffect == "resurrection") || (sEffect == "raise")){ eEffect = EffectResurrection(); iVis = VFX_IMP_HEALING_G; } else if(sEffect == "visual"){ eEffect = EffectVisualEffect(GetIntParam(sParams, 0)); } else { PrintString ("effect not defined: " + sEffect); return; } if (iVisualEffect >= 0) { if (iVisualEffect == 0) iVisualEffect = iVis; effect eVis = EffectVisualEffect(iVisualEffect); // Apply the visual effect to the target if (iVisType == DURATION_TYPE_INSTANT) { ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); } else if (iVisType == DURATION_TYPE_TEMPORARY) { // link temporary visual effects to the actual effect. eEffect = EffectLinkEffects(eEffect, eVis); } } ApplyEffectToObject(iDurationType, eEffect, oTarget, fDuration); PrintString ("Applied " + sEffect + " effect to " + GetName(oTarget) + " with Duration " + IntToString(iDurationType) + " " + FloatToString(fDuration)); } // ga_enable_scripts /* restores the saved event handlers */ // ChazM 12/21/05 // #include "ginc_param_const" #include "ginc_event_handlers" void main(string sTarget) { object oTarget = GetTarget(sTarget); RestoreEventHandlers(oTarget); DeleteSavedEventHandlers(oTarget); } // ga_end_game( string sEndMovie ) void main( string sEndMovie ) { EndGame( sEndMovie ); } // ga_face_target(string sFacer, string sTarget, int bLockOrientation) /* This script commands sFacer to face sTarget. Parameters: string sFacer = Tag of object that will do the facing. Default is OWNER string sTarget = Tag of object that sFacer will orient towards. int bLockOrientation = If =1, dialog manager will stop adjusting sFacer's facing for the active dialog. */ // BMA-OEI 1/09/06 // EPF 6/22/06 second parameter now uses GetTarget so param constants can be specified for both parameters. #include "ginc_actions" #include "ginc_param_const" void main(string sFacer, string sTarget, int bLockOrientation) { object oFacer = GetTarget(sFacer, TARGET_OWNER); object oTarget = GetTarget(sTarget); vector vTarget = GetPosition(oTarget); AssignCommand(oFacer, ActionDoCommand(SetFacingPoint(vTarget, bLockOrientation))); AssignCommand(oFacer, ActionWait(0.5f)); } // ga_faction_join /* This script makes sTarget join a new faction. sTarget - The target who's faction will change (see Target's note). sTargetFaction - Either one of the 4 standard factions $COMMONER, $DEFENDER, $HOSTILE, $MERCHANT or a target who's faction is to be joined (must be a creature) */ // ChazM 2/25/05 // DBR 11/09/06 - TargetFactionMember was using wrong target string #include "ginc_param_const" #include "nw_i0_generic" void main(string sTarget, string sTargetFaction) { object oTarget = GetTarget(sTarget); int iFaction = GetStandardFaction(sTargetFaction); if (iFaction != -1) { ChangeToStandardFaction(oTarget, iFaction); PrintString ("Changed to standard faction " + sTargetFaction ); } else { object oTargetFactionMember = GetTarget(sTargetFaction); ChangeFaction(oTarget, oTargetFactionMember); PrintString ("Changed to same faction as " + GetName(oTarget)); } AssignCommand(oTarget, DetermineCombatRound()); } // ga_faction_rep /* This script makes sTarget be viewed differently by a faction. sTarget - The target who will be viewed differently (see Target's note). sTargetFaction - Either one of the 4 standard factions $COMMONER, $DEFENDER, $HOSTILE, $MERCHANT or a target who belongs to the faction (may or may not need to be a creature) sChange - the amount to change the faction reputation by. (May later be ammended to allow setting). */ // ChazM 2/25/05 #include "ginc_param_const" #include "nw_i0_generic" void main(string sTarget, string sTargetFaction, string sChange) { object oTarget = GetTarget(sTarget); int iChange = StringToInt(sChange); if(!GetIsObjectValid(oTarget)) { PrintString ("Invalid Target"); return; } int iFaction = GetStandardFaction(sTargetFaction); if (iFaction == -1) { object oTargetFaction = GetTarget(sTargetFaction); if(GetIsObjectValid(oTargetFaction)) { AdjustReputation(oTarget, oTargetFaction, iChange); PrintString ("adjust faction reputation for " + GetName(oTarget) + " with faction of " + sTargetFaction + " by " + IntToString(iChange)); // this may be guy in completely different area, use nearest enemy instead in all cases //AssignCommand(oTargetFaction, DetermineCombatRound()); } } else { int iNewReputation = GetStandardFactionReputation(iFaction, oTarget) + iChange; SetStandardFactionReputation(iFaction, iNewReputation, oTarget); PrintString ("adjust faction reputation for " + GetName(oTarget) + " with " + sTargetFaction + " by " + IntToString(iChange)); // need to find closest and set to Determine Combat Round. } object oNearestEnemy = (GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oTarget)); AssignCommand(oNearestEnemy, DetermineCombatRound()); } // ga_fade_from_black // // wrapper function for FadeToBlackParty() to fade all party members from black. If the screen // had previously faded into a specific color, FadeToBlackParty() will fade back from that color. // // fSpeed controls how quickly, in seconds, the screen will fade to black. Setting this to 0 will // result in an instant fade from black. Standard value is 1.0. // // bColor allows users to specify what color the screen should fade back from. Basic colorlist: // 0 = black // Note: bColor // // CGaw 2/13/06 - Created. #include "ginc_cutscene" void main(float fSpeed) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); FadeToBlackParty(oPC, 0, fSpeed); } // ga_fade_to_black // // wrapper function for FadeToBlackParty() to fade all party members to black. // // fSpeed controls how quickly, in seconds, the screen will fade to black. Setting this to 0 will // result in an instant fade to black. // // fFailsafe indicates the maximum lenght of time, in seconds, that the screen will remain black // before automatically fading back in. Leave at 0.0 to use the default value of 15 seconds. // nColor allows users to specify what color the screen should fade into. Basic colorlist: // 0 = black, 16777215 = white. Hex Values for colors may be found in NWN2_Colors.2da, though // they must be converted to decimal form before use. // // CGaw 2/13/06 - Created. // CGaw 3/10/06 - Added color value information. // ChazM 9/26/06 - changed fFailsafe default. #include "ginc_cutscene" #include "ginc_math" void main(float fSpeed, float fFailsafe, int nColor) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if (IsFloatNearInt(fFailsafe, 0)) fFailsafe = 15.0f; FadeToBlackParty(oPC, 1, fSpeed, fFailsafe, nColor); } // ga_floating_str_ref /* Do floaty str ref text on PC speaker */ // ChazM 6/27/06 #include "ginc_debug" void main(int iStrRef) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); string sStrRef = GetStringByStrRef(iStrRef); //PrettyDebug ("Doing floaty text " + sStrRef + " on " + GetName(oPC)); FloatingTextStrRefOnCreature(iStrRef, oPC); } // ga_floating_text /* Do floaty text on PC speaker */ // ChazM 6/27/06 #include "ginc_debug" void main(string sText) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); // PrettyDebug ("Doing floaty text on " + GetName(oPC)); FloatingTextStringOnCreature(sText, oPC); } // ga_force_exit /* Wrapper for ForceExit, which makes a creature "exit" by moving it to a location and then removing it. Params: sCreatureTag - tag of the exiting creature sWPTag - tag of the waypoint (or object) to move to. bRun - 0 = walk; 1 = run When the creature reaches the specified loaction he will be destroyed, or in the case of roster members, despawned. Note: This is inteded to always work, and will remove flags such as plot and not-destroyable from the creature before attempting to destroy it. */ // EPF // ChazM 6/22/06 - just a comment change. // ChazM 9/18/06 - more comment changes. #include "ginc_misc" void main(string sCreatureTag, string sWPTag, int bRun) { //PrettyDebug("Forcing Exit!"); ForceExit(sCreatureTag, sWPTag, bRun); } // ga_gint_max /* This script changes a global int variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5" (Set to 5) "=-2" (Set to -2) "+3" (Add 3) "+" (Add 1) "++" (Add 1) "-4" (Subtract 4) "-" (Subtract 1) "--" (Subtract 1) int iMin = Minimum Value int iRule = Special case rule if both the original value and the new calculated value are above the maximum, apply the following rule: 0 - make no change to the original value 1 - set to maximum value 2 - use least of either the original or the changed value. */ // ChazM 8/26/05 #include "ginc_var_ops" void main(string sVariable, string sChange, int iMax, int iRule) { int nOldValue = GetGlobalInt(sVariable); int nNewValue = CalcNewIntValue(nOldValue, sChange); if (nNewValue > iMax) { if (nOldValue > iMax) { if (iRule == 0) return; // stick w/ old value if (iRule == 1) nNewValue = iMax; if (iRule == 2) if (nOldValue < nNewValue) return; // stick w/ old value, else just use new value } else nNewValue = iMax; } // Debug Message - comment or take care of in final //SendMessageToPC( oPC, sTagOver + "'s variable " + sScript + " is now set to " + IntToString(nChange) ); SetGlobalInt(sVariable, nNewValue); } // ga_gint_min /* This script changes a global int variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5" (Set to 5) "=-2" (Set to -2) "+3" (Add 3) "+" (Add 1) "++" (Add 1) "-4" (Subtract 4) "-" (Subtract 1) "--" (Subtract 1) int iMin = Minimum Value int iRule = Special case rule if both the original value and the new calculated value are below the minimum, apply the following rule: 0 - make no change to the original value 1 - set to minimum value 2 - use larget of either the original or the changed value. */ // ChazM 8/26/05 #include "ginc_var_ops" void main(string sVariable, string sChange, int iMin, int iRule) { int nOldValue = GetGlobalInt(sVariable); int nNewValue = CalcNewIntValue(nOldValue, sChange); if (nNewValue < iMin) { if (nOldValue < iMin) { if (iRule == 0) return; // stick w/ old value if (iRule == 1) nNewValue = iMin; if (iRule == 2) if (nOldValue > nNewValue) return; // stick w/ old value, else just use new value } else nNewValue = iMin; } // Debug Message - comment or take care of in final //SendMessageToPC( oPC, sTagOver + "'s variable " + sScript + " is now set to " + IntToString(nChange) ); SetGlobalInt(sVariable, nNewValue); } // ga_give_feat /* This gives a feat to a creature, player or players. sTarg = The creature to give the feat to. If blank, assign to PC nFeat = The number of the feat. See nwscript.nss for a list of feats. bCheckReq = Check if the creature meets the feat's prerequisites before adding. bAllPCs = If set to 1 it gives the feat to all the PCs (MP only). */ // TDE 3/4/06 // EPF 7/21/06 -- using GetTarget instead of GetObjectByTag() #include "ginc_param_const" void main(string sTarg, int nFeat, int bCheckReq, int bAllPCs) { object oTarg; object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if ( sTarg == "" ) { if ( !bAllPCs ) FeatAdd(oPC, nFeat, bCheckReq); else { oTarg = GetFirstPC(); while(GetIsObjectValid(oTarg)) { FeatAdd(oTarg, nFeat, bCheckReq); oTarg = GetNextPC(); } } } else { oTarg = GetTarget(sTarg); FeatAdd(oTarg, nFeat, bCheckReq); } } // ga_give_gold /* This gives the player some gold nGP = The amount of gold coins given to the PC nAllPCs = If set to 1 it gives gold to all the PCs (MP only) */ // FAB 9/30 void main(int nGP, int nAllPCs) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if ( nAllPCs == 0 ) GiveGoldToCreature( oPC,nGP ); else { object oTarg = GetFirstPC(); while(GetIsObjectValid(oTarg)) { GiveGoldToCreature( oTarg,nGP ); oTarg = GetNextPC(); } } } // ga_give_inventory /* This script takes items from sGiver's inventory and gives it to sReceiver. Parameters: string sGiver = Tag of object giving items. Default is OWNER. string sReceiver = Tag of object receiving items. Default is PC. int iInventoryContents = Which items to donate: 0 = All inventory items, equipped items and gold. (Giver must be creature) 1 = All inventory items only. 2 = All equipped items only. (Giver must be creature) */ // CGaw 3/10/06 // ChazM 3/15/06 - minor changes #include "ginc_item" #include "ginc_param_const" void main(string sGiver, string sReceiver, int iInventoryContents) { object oGiver = GetTarget(sGiver, TARGET_OWNER); object oReceiver = GetTarget(sReceiver, TARGET_PC); PrettyDebug ("sGiver = " + GetName(oGiver)); PrettyDebug ("sReceiver = " + GetName(oReceiver)); switch(iInventoryContents) { case 0: GiveEverything(oGiver, oReceiver); break; case 1: GiveAllInventory(oGiver, oReceiver); break; case 2: GiveAllEquippedItems(oGiver, oReceiver); break; } } // ga_give_item( string sTemplate, int nQuantity, int bAllPCs ) /* Creates item on PC(s) Parameters: string sTemplate = Item blueprint ResRef int nQuantity = Stack size for item (default: 1) int bAllPCs = If =1 create item on all player characters (MP) */ // FAB 9/30 // ChazM 10/19/05 - check if item is stackable and if not then give the quantity 1 at a time. // EPF 7/27/06 -- complete rewrite to address a bug and a number of stylistic pet peeves. Also // using a new method of tracking whether an item is stackable that Dan suggested. #include "ginc_debug" void CreateItemsOnObject( string sTemplate, object oTarget=OBJECT_SELF, int nItems=1 ); void main( string sTemplate, int nQuantity, int bAllPCs ) { object oPC = GetPCSpeaker(); if ( GetIsObjectValid(oPC) == FALSE ) { oPC = OBJECT_SELF; } // default stack size if ( nQuantity < 1 ) { nQuantity = 1; } if ( bAllPCs == FALSE ) { CreateItemsOnObject( sTemplate, oPC, nQuantity ); } else { oPC = GetFirstPC(); while ( GetIsObjectValid(oPC) == TRUE ) { CreateItemsOnObject( sTemplate, oPC, nQuantity ); oPC = GetNextPC(); } } } void CreateItemsOnObject( string sTemplate, object oTarget=OBJECT_SELF, int nItems=1 ) { int i = 1; while ( i <= nItems ) { CreateItemOnObject( sTemplate, oTarget, 1 ); i++; } } // ga_give_item_global_int /* This gives the player a number of items. The number is defined by a global int sItemRR = This is the string name of the item's ResRef sGlobalNum = The string of the global integer that contains the number of items to give nAllPCs = If set to 1 it gives the item to all PCs (MP only) */ // TDE 7/19/06 //Returns TRUE if oItem is stackable int GetIsStackableItem(string sItemRR) { //Must have a chest tagged checkchest //object oCopy = CopyItem(oItem, GetObjectByTag("checkchest")); object oCheck = GetObjectByTag("checkchest"); if (!GetIsObjectValid(oCheck)) oCheck = OBJECT_SELF; object oCopy = CreateItemOnObject(sItemRR, oCheck, 2); //Set the stacksize to two //SetItemStackSize(oCopy, 2); //Check if it really is two - otherwise, not stackable! int bStack=GetItemStackSize(oCopy)==2; //Destroy the test copy DestroyObject(oCopy); //Return bStack which is TRUE if item is stackable return bStack; } void CreateItemsOnObject(string sItemTemplate, object oTarget, int nNumToCreate) { int i; if(nNumToCreate > 1) { if (GetIsStackableItem(sItemTemplate)) { CreateItemOnObject(sItemTemplate, oTarget, nNumToCreate); } else for (i=1; i<=nNumToCreate; i++) { CreateItemOnObject(sItemTemplate, oTarget); } } } void main(string sItemRR, string sGlobalNum, int nAllPCs) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); // Check the global integer for the number of items to give int nQuantity = GetGlobalInt(sGlobalNum); if ( nQuantity == 0 ) nQuantity = 1; if ( nAllPCs == 0 ) CreateItemsOnObject(sItemRR, oPC, nQuantity ); else { object oTarg = GetFirstPC(); while(GetIsObjectValid(oTarg)) { CreateItemsOnObject( sItemRR,oTarg,nQuantity ); oTarg = GetNextPC(); } } } // ga_give_partial_quest_xp // // Give everyone experience for completing a quest. The experience goes to // ALL PCs in the party. Distinguished from ga_give_quest_xp in that you can specify the percentage // of the quest experience you want to give out, so, say if you have a 4-part quest, you could // award 25% of the experience for completing each portion. There is a cap in place so you can't // accidentally award more than 100% overall. // EPF 3/15/06 #include "ginc_journal" void main(string sQuestTag, int nPercentXP) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); RewardPartyCappedQuestXP(oPC, sQuestTag, nPercentXP); } // ga_give_quest_xp // // Give everyone experience for completing a quest. The experience goes to // ALL PCs in the party. // EPF 3/15/06 #include "ginc_journal" void main(string sQuestTag) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); RewardPartyQuestXP(oPC, sQuestTag); } // ga_give_xp /* This gives the player some experience nXP = The amount of experience given to the PC nAllPCs = If set to 1 it gives XP to all the PCs (MP only) */ // FAB 9/30 void main(int nXP, int nAllPCs) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if ( nAllPCs == 0 ) GiveXPToCreature(oPC, nXP ); else { object oTarg = GetFirstPC(); while(GetIsObjectValid(oTarg)) { GiveXPToCreature( oTarg,nXP ); oTarg = GetNextPC(); } } } // ga_global_float /* This script changes a global float variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5.1" (Set to 5.1) "=-2.3" (Set to -2.3) "+3.0" (Add 3.0) "+" (Add 1.0) "++" (Add 1.0) "-4.9" (Subtract 4.9) "-" (Subtract 1.0) "--" (Subtract 1.0) */ // FAB 10/7 // BMA 4/15/05 added set operator, "=n" void main(string sVariable, string sChange ) { float fChange; if (GetStringLeft(sChange, 1) == "=") { // BMA 4/15/05 sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = StringToFloat(sChange); } else if (GetStringLeft(sChange, 1) == "+") { // If sChange is just "+" then default to increment by 1 if (GetStringLength(sChange) == 1) { fChange = GetGlobalFloat(sVariable) + 1.0; } else // This means there's more than just "+" { if (GetSubString(sChange, 1, 1) == "+") // "++" condition { fChange = GetGlobalFloat(sVariable) + 1.0; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = StringToFloat(sChange) + GetGlobalFloat(sVariable); } } } else if (GetStringLeft(sChange, 1) == "-") { // If sChange is just "-" then default to increment by 1 if (GetStringLength(sChange) == 1) { fChange = GetGlobalFloat(sVariable) - 1.0; } else // This means there's more than just "-" { if (GetSubString(sChange, 1, 1) == "-") // "--" condition { fChange = GetGlobalFloat(sVariable) - 1.0; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = GetGlobalFloat(sVariable) - StringToFloat(sChange); } } } else { fChange = StringToFloat(sChange); if (sChange == "") fChange = GetGlobalFloat(sVariable) + 1.0; } SetGlobalFloat(sVariable, fChange); } // ga_global_int /* This script changes a global int variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5" (Set to 5) "=-2" (Set to -2) "+3" (Add 3) "+" (Add 1) "++" (Add 1) "-4" (Subtract 4) "-" (Subtract 1) "--" (Subtract 1) */ // FAB 10/7 // BMA 4/15/05 added set operator, "=n" // ChazM 5/4/05 mod #include "ginc_var_ops" void main(string sVariable, string sChange ) { int nOldValue = GetGlobalInt(sVariable); int nNewValue = CalcNewIntValue(nOldValue, sChange); // Debug Message - comment or take care of in final //SendMessageToPC( oPC, sTagOver + "'s variable " + sScript + " is now set to " + IntToString(nChange) ); SetGlobalInt(sVariable, nNewValue); } // ga_global_string /* This script changes a local string variable's value sScript = This is the name of the variable being changed sChange = This is what the local string is set to. */ // FAB 10/7 void main(string sScript, string sChange) { float fChange; object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); // Debug Message - comment or take care of in final //SendMessageToPC( oPC, sTagOver + "'s variable " + sScript + " is now set to " + sChange ); SetGlobalString( sScript, sChange ); } // ga_heal_pc /* This command heals the PC (and potentially their party) nHealPercent = This is the % damage the PC will be healed, 0 = 100% by default nFullParty = This is a boolean, by default it is FALSE and only the PC will be healed, 1 is full party */ // FAB 9/30 void main(int nHealPercent, int nFullParty) { object oPC = GetFirstPC(); object oComp; int nCurrentHP; int nHP; int nCompNumber = 1; // This is the companion number index effect eFX; if ( nHealPercent == 0 ) nHealPercent = 100; while( GetIsObjectValid(oPC) ) { nCurrentHP = GetCurrentHitPoints( oPC ); nHP = FloatToInt( IntToFloat(GetMaxHitPoints(oPC)) * IntToFloat(nHealPercent) / 100 ) - nCurrentHP; eFX = EffectHeal( nHP ); ApplyEffectToObject( DURATION_TYPE_PERMANENT,eFX,oPC ); oPC = GetNextPC(); } if ( nFullParty != 0 ) { oPC = GetFirstPC(); oComp = GetHenchman( oPC,1 ); while( GetIsObjectValid(oComp) ) { nCurrentHP = GetMaxHitPoints( oComp ); nHP = FloatToInt( IntToFloat(nCurrentHP) * IntToFloat(nHealPercent) / 100 ) - nCurrentHP; eFX = EffectHeal( nHP ); ApplyEffectToObject( DURATION_TYPE_PERMANENT,eFX,oComp ); nCompNumber++; oComp = GetHenchman( oPC,nCompNumber ); } } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_henchman_add //:: //:: Adds a target creature to your party as a henchman (not a companion). //:: //:: Parameters: //:: sTarget - tag of the creature you want to add //:: bForce - if set to 1, sTarget will be added even if player already has maximum henchman //:: sMaster - The Creature you are adding the henchman to (default is PC Speaker) //:: bOverrideBehavior - if set to 1, sTarget's event handlers (scripts) will be replaced with henchman ones. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 #include "ginc_param_const" #include "ginc_henchman" void main(string sTarget, int bForce, string sMaster, int bOverrideBehavior) { object oMaster,oHench; if (sMaster=="") oMaster=(GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); else oMaster=GetTarget(sMaster); oHench =GetTarget(sTarget); if (!GetIsObjectValid(oMaster))//tests for safety { PrintString("ga_henchman_add: Couldn't find master: "+sMaster); return; } if (!GetIsObjectValid(oHench)) { PrintString("ga_henchman_add: Couldn't find henchman: "+sTarget); return; } HenchmanAdd(oMaster,oHench,bForce,bOverrideBehavior); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_henchman_remove //:: //:: Removes a target creature from your party (must be a henchman, not a companion). //:: //:: Parameters: //:: sTarget - tag of the creature you want to remove. Default is NPC speaker //:: sOptionalMasterTag - No longer used. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 // ChazM 10/18/06 - sOptionalMasterTag no longer used. #include "ginc_param_const" #include "ginc_henchman" // sOptionalMasterTag no longer used void main(string sTarget, string sOptionalMasterTag) { object oMaster, oHench; oHench = GetTarget(sTarget); if (!GetIsObjectValid(oHench)) //does he exist? { PrettyDebug("ga_henchman_remove: Couldn't find henchman: " + sTarget); return; } oMaster = GetMaster(oHench); if (!GetIsObjectValid(oMaster)) //Safety first, ladies and gentlemen { PrettyDebug("ga_henchman_remove: Couldn't reference master."); return; } HenchmanRemove(oMaster,oHench); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_henchman_replace //:: //:: Repalces a target henchman from your party with another (henchmen are not companions). //:: //:: Parameters: //:: sOld - tag of the creature you want to remove as a companion. //:: sNew - tag of the creature you want to add as a companion. //:: bForce - if set to 1, sTarget will be added even if player already has maximum henchman //:: bOverrideBehavior - if set to 1, sTarget's event handlers (scripts) will be replaced with henchman ones. //:: sOptionalMasterTag - OPTIONAL - if ga_henchman_add wasn't used to add the henchman, you can supply the master tag here. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 #include "ginc_param_const" #include "ginc_henchman" void main(string sOld, string sNew, int bForce, int bOverrideBehavior, string sOptionalMasterTag) { object oMaster=OBJECT_INVALID,oNew,oOld; if (sOld=="") //Get the old henchman oOld =GetLastSpeaker(); else oOld =GetTarget(sOld); if (!GetIsObjectValid(oOld)) //does he exist? { PrintString("ga_henchman_replace: Couldn't find henchman: "+sNew); return; } if (sNew=="") //Get the new henchman oNew =GetLastSpeaker(); else oNew =GetTarget(sNew); if (!GetIsObjectValid(oNew)) //does he exist? { PrintString("ga_henchman_replace: Couldn't find henchman: "+sOld); return; } //Get the Master if (sOptionalMasterTag!="") //if a tag was supplied, use that oMaster=GetTarget(sOptionalMasterTag); if (!GetIsObjectValid(oMaster)) //if we still don't have a master, try checking for a stored value oMaster=GetLocalObject(oOld,sMasterRef); if (!GetIsObjectValid(oMaster)) //if we still don't have a master, try using the PC Speaker oMaster=(GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if (!GetIsObjectValid(oMaster)) //Safety first, ladies and gentlemen { PrintString("ga_henchman_replace: Couldn't reference master."); return; } //Ok, boot out the old henchman HenchmanRemove(oMaster,oOld); //And welcome in the new henchman HenchmanAdd(oMaster,oNew,bForce,bOverrideBehavior); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_henchman_setmax //:: //:: Sets the maximum number of allowed Henchmen (henchmen are not companions). //:: //:: Parameters: //:: sChange - Acts just like ga_local_int, give it the string of your change. //:: = VALUE (EFFECT) //:: "5" (Set to 5) //:: "=-2" (Set to -2) //:: "+3" (Add 3) //:: "+" (Add 1) //:: "++" (Add 1) //:: "-4" (Subtract 4) //:: "-" (Subtract 1) //:: "--" (Subtract 1) //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 - I so ripped this off of ga_local_int. Thank you FAB. #include "ginc_param_const" #include "ginc_var_ops" //#include "ginc_henchman" void main(string sChange) { int nOldValue = GetMaxHenchmen(); int nNewValue = CalcNewIntValue(nOldValue, sChange); SetMaxHenchmen(nNewValue); } // ga_journal(string sCategoryTag, int nEntryID, int bAllPartyMembers, int bAllPlayers, int bAllowOverrideHigher) /* Wrapper to add an entry to PCSpeaker's journal. Parameters: string sCategoryTag = The tag of the Journal category (case sensitive). int nEntryID = The ID of the Journal entry. int bAllPartyMembers = If =1, the entry is added to the journal of all of oCreature's Party. (Default: =1) int bAllPlayers = If =1, the entry will show up in the journal of all PCs in the module. (Default: =0) int bAllowOverrideHigher = If =1, override restriction that nState must be > current Journal Entry. (Default: =0) */ // BMA-OEI 10/14/05 // BMA-OEI 1/11/06 removed default params void main(string sCategoryTag, int nEntryID, int bAllPartyMembers, int bAllPlayers, int bAllowOverrideHigher) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); AddJournalQuestEntry(sCategoryTag, nEntryID, oPC, bAllPartyMembers, bAllPlayers, bAllowOverrideHigher); } // ga_jump(string sDestination, string sTarget, float fDelay) /* Jump an object to a waypoint or another object. Parameters: string sDestination = Tag of waypoint or object to jump to. string sTarget = Tag of object to jump. Default is OWNER float fDelay = Delay before JumpToObject() */ // TDE 3/9/05 // ChazM 3/11/05 // BMA 7/13/05 changed Delay/Assign to Assign/Delay // BMA-OEI 1/11/06 removed default param #include "ginc_param_const" void main(string sDestination, string sTarget, float fDelay) { object oDestination = GetTarget(sDestination); object oTarget = GetTarget(sTarget, TARGET_OWNER); AssignCommand(oTarget, DelayCommand(fDelay, JumpToObject(oDestination))); } // ga_jump_faction(string sTagOfMember, string sTagOfWayPoint, int iFormation, string sFormationParams) /* Jump faction into formation at sTagOfWayPoint. Parameters: string sTagOfMember = Tag of member in faction to jump. string sTagOfWayPoint = Tag of waypoint. int iFormation = DOES NOTHING. string sFormationParams = DOES NOTHING. */ // BMA 5/24/05 // ChazM 5/26/05 // ChazM 6/2/05 updated to work w/ new features // BMA-OEI 1/11/06 removed default param, use default U7 formation // ChazM 3/3/06 Added error message for when this is used in campaign on a PC to do an area transition #include "ginc_param_const" #include "ginc_group" #include "ginc_transition" void main(string sTagOfMember, string sTagOfWayPoint, int iFormation, string sFormationParams) { object oTarget = GetTarget(sTagOfMember, TARGET_OBJECT_SELF); //float fRadius = StringToFloat(sFormationParams); //if (fRadius <= 0.1f) fRadius = 10.0f; string sGroupName = "tempGroup"; ResetGroup(sGroupName); GroupAddFaction(sGroupName, oTarget, GROUP_LEADER_FIRST, TRUE); GroupSetBMAFormation(sGroupName); if (GetIsPC(oTarget) && (GetGlobalInt(VAR_GLOBAL_GATHER_PARTY)==1) && (GetArea(oTarget) != GetArea(GetWaypointByTag(sTagOfWayPoint))) ) { PrettyError("Area transition of PC's made using ga_jump_faction in a campaign module. Please report this as an error."); } GroupMoveToWP(sGroupName, sTagOfWayPoint, MOVE_JUMP_INSTANT); } // ga_jump_party_in_formation // CGaw 3/16/06 // // Jumps entire party to a waypoint in the formation specified. // // string sWaypoint - the string of tag to jump the party to. // // int iFormationNum - the number that corresponds to the formation you want the party // jumped in. // 0 = BenMa Formation - creates a standard party group formation: // 1 // 2 3 // 4 5 6 // 7 8 // 1 = Line Formation // 2 = Half circle formation, facing outward // 3 = Full circle formation, facing outward // 4 = Rectangle formation // // float fFormationTightness - float value to determine how far apart each party member // is from one another. Each formation type has a specified default value: // 0 = 1.5f // 1 = 1.5f // 2 = 1.5f // 3 = 1.5f // 4 = 1.5f // // int bDisableNoise - determines whether noise for imperfect group formations should // be applied. // 0 = default noise values applied (DEFAULT VALUE) // 1 = noise disabled // Note: To ensure that the party group appears in the expected formation, each party // member's associate state for "NW_ASC_MODE_STAND_GROUND" should be set to FALSE. // The global script ga_party_freeze can also be used to accomplish this. #include "ginc_group" void main(string sWaypoint, int iFormationNum, float fFormationTightness, int bDisableNoise) { object oPC = GetFirstPC(); string sGroupName = "Party_Jump_Group"; ResetGroup(sGroupName); GroupAddFaction(sGroupName, oPC, GROUP_LEADER_FIRST, TRUE); if (fFormationTightness < 0.1) { fFormationTightness = 1.5f; } switch(iFormationNum) { case 0: GroupSetBMAFormation(sGroupName, fFormationTightness); break; case 1: GroupSetLineFormation(sGroupName, fFormationTightness); break; case 2: GroupSetSemicircleFormation(sGroupName, FORMATION_SEMICIRCLE_FACE_OUT, fFormationTightness); break; case 3: GroupSetCircleFormation(sGroupName, FORMATION_HUDDLE_FACE_OUT, fFormationTightness); break; case 4: GroupSetRectangleFormation(sGroupName, fFormationTightness); break; default: GroupSetBMAFormation(sGroupName, fFormationTightness); break; } switch(bDisableNoise) { case 0: GroupSetNoise(sGroupName, 0.0f, 10.0f, 0.5f); break; case 1: break; default: GroupSetNoise(sGroupName, 0.0f, 10.0f, 0.5f); break; } GroupJumpToWP(sGroupName, sWaypoint); } // ga_jump_players(string sDestTag, int bWholeParty, int bOnlyThisArea) /* Jumps the PC party to a waypoint or object. Parameters: string sDestTag = Tag of waypoint or object to jump to. int bWholeParty = DOES NOTHING IN CAMPAIGN. If =0 then jump the PC only, else jump the PC's party. int bOnlyThisArea = DOES NOTHING */ // ChazM 3/11/05 // BMA-OEI 1/11/06 removed default params // EPF 2/6/06 -- fixed the loop in JumpParty to deal with multiple parties // ChazM 3/3/06 - replaced JumpParty() w/ JumpPartyToArea() script command. Modified to always jump whole party in campaign. #include "ginc_debug" #include "ginc_transition" // Jump oPC's whole party. // oPartyMember - member of the party to jump // oDestination - the destination (typically a waypoint object) // bOnlyThisArea - Jump only members of the party in the same area as oPartyMember? Default is true void JumpParty(object oPartyMember, object oDestination, int bOnlyThisArea) { object oThisArea = GetArea(oPartyMember); object oJumper = GetFirstFactionMember(oPartyMember, FALSE); if(GetIsPC(oJumper)) { oJumper = GetNextFactionMember(oPartyMember, FALSE); } while (GetIsObjectValid(oJumper) == TRUE) { if (!bOnlyThisArea || (GetArea(oJumper) == oThisArea)) { AssignCommand(oJumper, JumpToObject(oDestination)); } oJumper = GetNextFactionMember(oPartyMember, FALSE); } oJumper = GetFirstFactionMember(oPartyMember, TRUE); while (GetIsObjectValid(oJumper) == TRUE) { if (!bOnlyThisArea || (GetArea(oJumper) == oThisArea)) { AssignCommand(oJumper, JumpToObject(oDestination)); } oJumper = GetNextFactionMember(oPartyMember, TRUE); } } void main(string sDestTag, int bWholeParty, int bOnlyThisArea) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oDestination = GetObjectByTag(sDestTag); if (bWholeParty == 0 && GetGlobalInt(VAR_GLOBAL_GATHER_PARTY)==0) { AssignCommand(oPC, JumpToObject(oDestination)); } else { // BMA-OEI 6/14/06 SinglePartyTransition( oPC, oDestination ); //JumpPartyToArea(oPC, oDestination); //JumpParty(oPC, oDestination, bOnlyThisArea); } } // ga_load_mod // // Loads a module, including any data that may have been affected by the player during previous // visits. (As opposed to ga_start_mod, which gives you a brand-new copy of the module.) // sModule is the filename of the module, minus the .mod extension. // sWaypoint is the tag of the waypoint from which the player will begin the module. // If no waypoint is supplied, the module's default start location is used instead. // EPF 1/16/06 // BMA-OEI 4/12/06 - replaced LNM() with SRLM() #include "ginc_companion" void main( string sModule, string sWaypoint ) { SaveRosterLoadModule( sModule, sWaypoint ); } // ga_local_float(string sVariable, string sChange, string sTarget /* This script changes a local float variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5.1" (Set to 5.1) "=-2.3" (Set to -2.3) "+3.0" (Add 3.0) "+" (Add 1.0) "++" (Add 1.0) "-4.9" (Subtract 4.9) "-" (Subtract 1.0) "--" (Subtract 1.0) string sTarget = Target tag or identifier. If blank then use OBJECT_SELF */ // FAB 10/7 // BMA 4/15/05 added set operator, "=n" // BMA 4/27/05 added GetTarget() // BMA 7/19/05 added object invalid printstring #include "ginc_param_const" void main(string sVariable, string sChange, string sTarget) { float fChange; object oTarg = GetTarget(sTarget, TARGET_OBJECT_SELF); if (GetIsObjectValid(oTarg) == FALSE) PrintString("ga_local_string: " + sTarget + " is invalid"); if (GetStringLeft(sChange, 1) == "=") { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = StringToFloat(sChange); } else if (GetStringLeft(sChange, 1) == "+") { // If sChange is just "+" then default to increment by 1 if (GetStringLength(sChange) == 1) { fChange = GetLocalFloat(oTarg, sVariable) + 1.0; } else // This means there's more than just "+" { if (GetSubString(sChange, 1, 1) == "+") // "++" condition { fChange = GetLocalFloat(oTarg, sVariable) + 1.0; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = GetLocalFloat(oTarg, sVariable) + StringToFloat(sChange); } } } else if (GetStringLeft(sChange, 1) == "-") { // If sChange is just "-" then default to increment by 1 if (GetStringLength(sChange) == 1) { fChange = GetLocalFloat(oTarg, sVariable) - 1.0; } else // This means there's more than just "-" { if (GetSubString(sChange, 1, 1) == "-") // "--" condition { fChange = GetLocalFloat(oTarg, sVariable) - 1.0; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); fChange = GetLocalFloat(oTarg, sVariable) - StringToFloat(sChange); } } } else { fChange = StringToFloat(sChange); if (sChange == "") fChange = GetLocalFloat(oTarg, sVariable) + 1.0; } // Debug Message - comment or take care of in final SetLocalFloat(oTarg, sVariable, fChange); } // ga_local_int(string sVariable, string sChange, string sTarget) /* This script changes a local int variable's value Parameters: string sVariable = Name of variable to change string sChange = VALUE (EFFECT) "5" (Set to 5) "=-2" (Set to -2) "+3" (Add 3) "+" (Add 1) "++" (Add 1) "-4" (Subtract 4) "-" (Subtract 1) "--" (Subtract 1) string sTarget = Target tag or identifier. If blank then use OBJECT_SELF */ // FAB 10/7 // BMA 4/15/05 added set operator, "=n" // BMA 4/27/05 added GetTarget() // ChazM 5/4/05 moved CalcNewIntValue() to "ginc_var_ops" // BMA 7/19/05 added object invalid printstring #include "ginc_param_const" #include "ginc_var_ops" void main(string sVariable, string sChange, string sTarget) { object oTarg = GetTarget(sTarget, TARGET_OBJECT_SELF); if (GetIsObjectValid(oTarg) == FALSE) PrintString("ga_local_int: " + sTarget + " is invalid"); int nOldValue = GetLocalInt(oTarg, sVariable); int nNewValue = CalcNewIntValue(nOldValue, sChange); SetLocalInt(oTarg, sVariable, nNewValue); //PrintString(sTarget + "'s variable " + sVariable + " is now set to " + IntToString(nNewValue) ); } // ga_local_string(string sVariable, string sValue, string sTarget) /* This script changes a Target's local string variable's value. Parameters: string sVariable = The name of the variable. string sValue = The new value for the variable. string sTarget = The target's tag or identifier, if blank use OWNER */ // FAB 10/4 // BMA 4/27/05 - added GetTarget() // BMA 7/19/05 added object invalid printstring // BMA-OEI 7/28/05 - added debug printstring #include "ginc_param_const" void main(string sVariable, string sValue, string sTarget) { object oTarget = GetTarget(sTarget, TARGET_OWNER); PrintString("ga_local_string: Object '" + GetName(oTarget) + "' variable '" + sVariable + "' set to '" + sValue + "'"); SetLocalString(oTarget, sVariable, sValue); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_lock.nss //:: //:: Change the lock status of a door. If bLock is false, the door will //:: be unlocked. //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: EPF //:: Created on: 3/7/06 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_param_const" void main(string sDoorTag, int bLock) { object oDoor = GetTarget(sDoorTag); SetLocked(oDoor, bLock); } //ga_mapnote // Turns on and off map notes on the mini-map. // sTag - Tag of the mapnote to turn on or off // bActive - TRUE(1) will turn the map note on, making it visible to the player // FALSE(0) will turn off the map note, making it invisible to the player #include "ginc_param_const" void main(string sTag, int bActive) { SetMapPinEnabled(GetTarget(sTag),bActive); } // ga_move /* This moves someone to a waypoint. sWP = Lists the waypoint the object is moving to. nRun = Defaults to walk, set to 1 for running sTagOverride = If this is null, then OWNER runs the script. Otherwise the string is the tag name of who will run it */ // FAB 10/5 // ChazM 6/22/05 - changed to GetTarget() // ChazM 9/9/05 - modifed waypoint look up to also look for sWP w/o prepending "wp_" #include "ginc_param_const" void main(string sWP, int nRun, string sTagOverride) { object oTarg = OBJECT_SELF; object oWP = GetObjectByTag( "wp_" + sWP ); if (!GetIsObjectValid(oWP)) oWP = GetObjectByTag(sWP ); if (!GetIsObjectValid(oWP)) { PrintString("WARNING - ga_move: couldn't find waypoint: " + sWP); return; } if ( sTagOverride != "" ) oTarg = GetTarget(sTagOverride); AssignCommand(oTarg, ActionForceMoveToObject(oWP, nRun)); } // ga_move_exit /* This makes the object go to the exit (default nwc_exit) and then vanish nExitNumber = nwc_exit#N nRun = TRUE if you want the character to run there sWaypoint = go to waypoint nwc_#S then disappear sObject = if you don't want the OWNER to move, use the tag string here */ // FAB 9/29 // ChazM 6/29/06 - rewrote to use ForceExit() without changing functionality. #include "ginc_misc" string GetExitWaypoint(int nExitNumber, string sWaypoint) { string sWPTag; // No other parameters on the exit are set if ( nExitNumber == 0 && sWaypoint == "") { sWPTag = "nwc_exit"; } // An exit number is set else if ( sWaypoint == "") { sWPTag = "nwc_exit" + IntToString(nExitNumber); } // An exit string is set else { sWPTag = "nwc_" + sWaypoint; } return (sWPTag); } void main(int nExitNumber, int nRun, string sWaypoint, string sObject) { string sWPTag = GetExitWaypoint(nExitNumber, sWaypoint); object oWP = GetWaypointByTag(sWPTag); PrettyDebug(" Name of generic exit: " + GetName(oWP)); ForceExit(sObject, sWPTag, nRun); /* if ( sObject == "" ) { // No other parameters on the exit are set if ( nExitNumber == 0 && sWaypoint == "") { ActionForceMoveToObject(oWP,nRun ); } // An exit number is set else if ( sWaypoint == "") { ActionForceMoveToObject( GetWaypointByTag("nwc_exit" + IntToString(nExitNumber)),nRun ); } // An exit string is set else { ActionForceMoveToObject( GetWaypointByTag("nwc_" + sWaypoint),nRun ); } // Now queue up the actions for after they move ActionDoCommand( SetCommandable(TRUE) ); ActionDoCommand( DestroyObject(OBJECT_SELF) ); SetCommandable( FALSE ); } else { // This is who is going to be executing the command besides the OWNER object oTarg = GetObjectByTag( sObject ); int iCommandable = GetCommandable(oTarg); PrettyDebug(GetName(oTarg) + " commandable state is " + IntToString(iCommandable)); AssignCommand( oTarg, SetCommandable( TRUE ) ); PrettyDebug(GetName(oTarg) + " is Target of MoveExit"); // No other parameters on the exit are set if ( nExitNumber == 0 && sWaypoint == "") { PrettyDebug(" Using generic exit of " + GetName(oWP)); AssignCommand( oTarg, ActionForceMoveToObject( oWP,nRun ) ); } // An exit number is set else if ( sWaypoint == "") { AssignCommand( oTarg, ActionForceMoveToObject( GetWaypointByTag("nwc_exit" + IntToString(nExitNumber)),nRun ) ); } // An exit string is set else {` AssignCommand( oTarg, ActionForceMoveToObject( GetWaypointByTag("nwc_" + sWaypoint),nRun ) ); } // Now queue up the actions for after they move AssignCommand( oTarg, ActionDoCommand( SetCommandable(TRUE) ) ); AssignCommand( oTarg, ActionDoCommand( DestroyObject(OBJECT_SELF) ) ); AssignCommand( oTarg, SetCommandable( FALSE ) ); } */ } // ga_music_play /* Play battle music in current area */ // EPF 8/23/06 void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); MusicBattlePlay(oArea); } // ga_music_battle_restore /* Restore background music in current area. Restore with ga_music_restore. */ // EPF 8/23/06 #include "ginc_sound" void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); RestoreBattleMusicTrack(oArea); } // ga_music_battle_save /* Save background music in current area. Restore with ga_music_restore. */ // EPF 8/23/06 #include "ginc_sound" void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); SaveBattleMusicTrack(oArea); } // ga_music_battle_set /* Set battle music in current area to track nTrack As of 8/23/06, this was the track indexing. The latest can be found in ambientmusic.2da. 0. NO MUSIC From NWN1: --------- 1. rural day 2. rural day 2 3. rural night 4. forest day 5. forest day 2 6. forest night 7. generic dungeon 1 8. sewer 9. mines 1 10. mines 2 11. crypt 1 12. crypt 2 13. evil dungeon 1 14. evil dungeon 2 15. slums day 16. slums night 17. docks day 18. docks night 19. city wealthy 20. city market 21. city night 22. tavern 1 23. tavern 2 24. tavern 3 25. rich house 26. store 27. good temple 28. temple evil 29. nwn1 theme 30. nwn chapter 1 theme 31. nwn chapter 2 theme 32. nwn chapter 3 theme 33. nwn chapter 4 theme 34. rural battle 1 35. forest battle 1 36. forest battle 2 37. dungeon battle 1 38. dungeon battle 2 39. dungeon battle 3 (stinger) 40. city battle 1 41. city battle 2 42. city battle 3 43. city boss battle 44. forest boss battle 45. lizard boss battle 46. dragon boss battle 47. aribeth boss battle 48. end boss battle 49. good temple 2 50. castle 51. aribeth good theme 52. aribeth evil theme 53. arren gend theme 54. maugrim theme 55. morag theme 56. tavern 4 From NWN1 Expansion 1 --------------------- 57. desert battle 58. desert day 59. winter day 60. winter battle 61. desert night From NWN1 Expansion 2 --------------------- 62. x2 Theme 63. waterdeep theme 64. undermountain theme 65. rebel camp 66. fire plane 67. queen (?) theme 68. frozen hell 69. dracolich 70. small battle 71. medium battle 72. large battle 73. hell battle 74. boss battle 1 75. boss battle 2 From NWN2 --------- 95. west harbor theme 96. githyanki theme 97. githyanki battle 98. west harbor blown up 99. swamp 100. docks battle 101. docks battle looped 102. dungeon 103. neverwinter theme 104. neverwinter interior 105. west harbor attack 106. back alley 107. king of shadows combat 108. king of shadows theme 109. village 110. sunken flagon 111. crossroad keep theme 112. illefarn ruins theme 113. murder 114. ammon jerro theme 115. back alley battle */ // EPF 8/23/06 void main(int nTrack) { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); MusicBattleChange(oArea, nTrack); } // ga_music_battle_stop /* Stop battle music in current area */ // EPF 8/23/06 void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); MusicBattleStop(oArea); } // ga_music_play /* Play background music in current area */ // EPF 8/23/06 void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); MusicBackgroundPlay(oArea); } // ga_music_restore /* restore background music in current area */ // EPF 8/23/06 #include "ginc_sound" void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); RestoreMusicTrack(oArea); } // ga_music_save /* Save background music in current area. Restore with ga_music_restore. */ // EPF 8/23/06 #include "ginc_sound" void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); SaveMusicTrack(oArea); } // ga_music_set /* Set background music in current area to track nTrack nTime will have the following effects: nTime = 0: Change both Day and Night tracks nTime = 1: Change Day track only nTime = 2: Change Night track only As of 8/23/06, this was the track indexing. The latest can be found in ambientmusic.2da. 0. NO MUSIC From NWN1: --------- 1. rural day 2. rural day 2 3. rural night 4. forest day 5. forest day 2 6. forest night 7. generic dungeon 1 8. sewer 9. mines 1 10. mines 2 11. crypt 1 12. crypt 2 13. evil dungeon 1 14. evil dungeon 2 15. slums day 16. slums night 17. docks day 18. docks night 19. city wealthy 20. city market 21. city night 22. tavern 1 23. tavern 2 24. tavern 3 25. rich house 26. store 27. good temple 28. temple evil 29. nwn1 theme 30. nwn chapter 1 theme 31. nwn chapter 2 theme 32. nwn chapter 3 theme 33. nwn chapter 4 theme 34. rural battle 1 35. forest battle 1 36. forest battle 2 37. dungeon battle 1 38. dungeon battle 2 39. dungeon battle 3 (stinger) 40. city battle 1 41. city battle 2 42. city battle 3 43. city boss battle 44. forest boss battle 45. lizard boss battle 46. dragon boss battle 47. aribeth boss battle 48. end boss battle 49. good temple 2 50. castle 51. aribeth good theme 52. aribeth evil theme 53. arren gend theme 54. maugrim theme 55. morag theme 56. tavern 4 From NWN1 Expansion 1 --------------------- 57. desert battle 58. desert day 59. winter day 60. winter battle 61. desert night From NWN1 Expansion 2 --------------------- 62. x2 Theme 63. waterdeep theme 64. undermountain theme 65. rebel camp 66. fire plane 67. queen (?) theme 68. frozen hell 69. dracolich 70. small battle 71. medium battle 72. large battle 73. hell battle 74. boss battle 1 75. boss battle 2 From NWN2 --------- 95. west harbor theme 96. githyanki theme 97. githyanki battle 98. west harbor blown up 99. swamp 100. docks battle 101. docks battle looped 102. dungeon 103. neverwinter theme 104. neverwinter interior 105. west harbor attack 106. back alley 107. king of shadows combat 108. king of shadows theme 109. village 110. sunken flagon 111. crossroad keep theme 112. illefarn ruins theme 113. murder 114. ammon jerro theme 115. back alley battle */ // EPF 8/23/06 const int TIME_BOTH = 0; const int TIME_DAY = 1; const int TIME_NIGHT = 2; #include "ginc_sound" void main(int nTrack, int nTime) { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); if(nTime == TIME_BOTH || nTime == TIME_DAY) { MusicBackgroundChangeDay(oArea,nTrack); } if(nTime == TIME_BOTH || nTime == TIME_NIGHT) { MusicBackgroundChangeNight(oArea, nTrack); } } // ga_music_stop /* Stop background music in current area */ // EPF 8/23/06 void main() { object oPC = GetPCSpeaker(); if(!GetIsObjectValid(oPC)) { oPC = OBJECT_SELF; } object oArea = GetArea(oPC); MusicBackgroundStop(oArea); } // ga_object_events_clear /* saves off the event handlers as local vars and clears the event handlers for the object can't be used on areas or modules */ // ChazM 4/30/06 #include "ginc_event_handlers" void main (string sObjectTag) { object oObject = GetObjectByTag(sObjectTag); if (GetIsObjectValid(oObject)) { SafeClearEventHandlers(oObject); } } // ga_object_events_restore /* restore saved off event handlers from local vars and clear the local vars can't be used on areas or modules */ // ChazM 4/30/06 #include "ginc_event_handlers" void main (string sObjectTag) { object oObject = GetObjectByTag(sObjectTag); if (GetIsObjectValid(oObject)) { SafeRestoreEventHandlers(oObject); } } // ga_open_store /* Opens store with tag sTag for the PC Speaker. nMarkUp/nMarkDown are a percentage value that modifies the base price for an item. Function also adds or subtracts numbers to the markup and markdown values depending on the result of the appraise skill check. */ // ChazM 5/9/06 - changed to gplotAppraiseOpenStore // ChazM 8/30/06 - new appraise open store function used. //#include "ginc_misc" //#include "nw_i0_plot" #include "ginc_param_const" #include "ginc_item" void main(string sTag, int nMarkUp, int nMarkDown) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); //OpenStore(GetTarget(sTag), oPC, nMarkUp, nMarkDown); N2_AppraiseOpenStore(GetTarget(sTag), oPC, nMarkUp, nMarkDown); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_party_add.nss //:: //:: Attempt to add Roster Member to the PC's party. Fails if Roster Member //:: is already a member of a party, or if party size limit has been reached. //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: BMA-OEI //:: Created on: 10/18/05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_debug" void main(string sRosterName) { object oPC = GetFirstPC(); //int nPartyLimit = GetRosterNPCPartyLimit(); int bResult = 0; // TODO: replace with actual nPartyLimit < nCurrentPartySize if (1 > 0) { bResult = AddRosterMemberToParty(sRosterName, oPC); if (bResult == TRUE) { PrettyMessage("ga_party_add: successfully added " + sRosterName); } else { PrettyError("ga_party_add: error adding " + sRosterName); } } else { PrettyError("ga_party_add: party limit exceeded! could not add " + sRosterName); } } // ga_party_face_target(string sFacer, string sTarget, int bLockOrientation) /* This script commands the party to face sTarget. Parameters: string sFactionMember = the tag of any member of the party faction will do. Can also be a GetTarget() constant. string sTarget = Tag of object that the party will orient towards. int bLockOrientation = If =1, dialog manager will stop adjusting sFacer's facing for the active dialog. */ // BMA-OEI 1/09/06 // EPF 6/22/06 second parameter now uses GetTarget so param constants can be specified for both parameters. #include "ginc_actions" #include "ginc_param_const" void main(string sFactionMember, string sTarget, int bLockOrientation) { object oFM = GetTarget(sFactionMember); object oTarget = GetTarget(sTarget); object oFacer; vector vTarget = GetPosition(oTarget); oFacer = GetFirstFactionMember(oFM, FALSE); while(GetIsObjectValid(oFacer)) { AssignCommand(oFacer, ActionDoCommand(SetFacingPoint(vTarget, bLockOrientation))); AssignCommand(oFacer, ActionWait(0.5f)); oFacer = GetNextFactionMember(oFM, FALSE); } } // ga_party_freeze() /* Freeze PC party for cutscene. Temporarily save NW_ASC_MODE_STAND_GROUND state. Use ga_party_unfreeze() to restore NW_ASC_MODE_STAND_GROUND state. */ // BMA-OEI 3/7/06 #include "ginc_cutscene" void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { // Save current stand ground state SaveStandGroundState(oMember); // Force all members to stand ground SetAssociateState(NW_ASC_MODE_STAND_GROUND, TRUE, oMember); // Clear action queue and combat state AssignCommand(oMember, ClearAllActions(TRUE)); oMember = GetNextFactionMember(oPC, FALSE); } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_party_size.nss //:: //:: Set number of Roster NPC slots available in the Party Selection GUI //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: BMA-OEI //:: Created on: 10/18/05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_debug" void main(int nSize) { PrettyMessage("ga_party_limit: setting roster slot size to " + IntToString(nSize)); SetRosterNPCPartyLimit(nSize); } // ga_party_unfreeze() /* Unfreeze PC party at end of cutscene. Restore NW_ASC_MODE_STAND_GROUND state. Use ga_party_freeze() to save NW_ASC_MODE_STAND_GROUND state. */ // BMA-OEI 3/7/06 #include "ginc_cutscene" void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oFirstPCInFaction = GetFirstFactionMember(oPC,TRUE); if(!GetIsObjectValid(oFirstPCInFaction)) { oPC = GetPrimaryPlayer(); if(!GetIsObjectValid(oPC)) { oPC = GetFirstPC(); } } object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { // Set NW_ASC_MODE_STAND_GROUND to pre-ga_party_freeze() value LoadStandGroundState(oMember); oMember = GetNextFactionMember(oPC, FALSE); } } //ga_play_animation // Conversation script wrapper for ActionPlayAnimation() command. // // sTarget - tag of creature to play animation - default is conversation owner. // iAnim - ANIMATION CONSTANT. // fSpeed - speed animation plays at. // fDurationSeconds - Duration of animation (doesn't apply to fire & forget animations) // fDelayUntilStart - Not to be confused with DURATION, this controls how long after the node starts in seconds to play the animation. //ChazM 9/22/06 #include "ginc_param_const" #include "ginc_math" void main(string sTarget, int iAnim, float fSpeed, float fDurationSeconds, float fDelayUntilStart) { if (IsFloatNearInt(fSpeed, 0)) fSpeed = 1.0f; object oTarget = GetTarget(sTarget); if (GetIsObjectValid(oTarget)) { if (IsFloatNearInt(fDelayUntilStart, 0)) AssignCommand(oTarget, PlayAnimation(iAnim,fSpeed,fDurationSeconds)); else AssignCommand(oTarget, DelayCommand(fDelayUntilStart,PlayAnimation(iAnim,fSpeed,fDurationSeconds))); } } //ga_play_custom_animation // Conversation script wrapper for PlayCustomAnimation() command. // // sTarget - tag of creature to play animation - default is conversation owner. // sAnim - animation to play - uses PlayCustomAnimation's *, # and % rules. // bLoop - TRUE for looping, FALSE for single-shot. // fDelayUntilStart - Not to be confused with DURATION, this controls how long after the node starts in seconds to play the animation. // DBR 6/20/06 //EPF -- removed the AssignCommand from the delay code, since that seems to be a likely cause of interrupting animations. #include "ginc_param_const" void PlayCustomAnimationWrapper(object oTarget, string sAnim, int bLoop) //so it returns a void { PlayCustomAnimation(oTarget,sAnim,bLoop); } void main(string sTarget, string sAnim, int bLoop=0, float fDelayUntilStart=0.0f) { object oTarget = GetTarget(sTarget); if (GetIsObjectValid(oTarget)) { if (fDelayUntilStart==0.0f) PlayCustomAnimation(oTarget,sAnim,bLoop); else DelayCommand(fDelayUntilStart,PlayCustomAnimationWrapper(oTarget,sAnim,bLoop));//place the delaycommand on the creature as well } } // ga_play_sound // // Play sound file sSound on object with tag sTarget. // Note: Advise using this on creatures only. Typically calls to play the sound on the module, // the area, or even a dynamic placeable fail, because I believe this actually goes into an action // queue, despite the function's name lacking the word "action." // Also Note: Do not specify the sound file's extension for sSound. If you want to play // as_pl_flatulence.wav, just enter in "as_pl_flatulence" for sSound. // Supplying the empty string for sTarget will just use the conversation owner as the target object. // EPF 7/6/06 #include "ginc_param_const" void main(string sSound, string sTarget, float fDelay) { object oTarget = GetTarget(sTarget, TARGET_OWNER); if(GetIsObjectValid(oTarget)) { AssignCommand(oTarget, DelayCommand(fDelay,PlaySound(sSound))); } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_play_voice_chat( int nVoiceChat, string sTag ) //:: //:: This is basically just a wrapper for PlayVoiceChat. /* * int nVoiceChat must be one of the following right-hand values: int VOICE_CHAT_ATTACK = 0; int VOICE_CHAT_BATTLECRY1 = 1; int VOICE_CHAT_BATTLECRY2 = 2; int VOICE_CHAT_BATTLECRY3 = 3; int VOICE_CHAT_HEALME = 4; int VOICE_CHAT_HELP = 5; int VOICE_CHAT_ENEMIES = 6; int VOICE_CHAT_FLEE = 7; int VOICE_CHAT_TAUNT = 8; int VOICE_CHAT_GUARDME = 9; int VOICE_CHAT_HOLD = 10; int VOICE_CHAT_GATTACK1 = 11; int VOICE_CHAT_GATTACK2 = 12; int VOICE_CHAT_GATTACK3 = 13; int VOICE_CHAT_PAIN1 = 14; int VOICE_CHAT_PAIN2 = 15; int VOICE_CHAT_PAIN3 = 16; int VOICE_CHAT_NEARDEATH = 17; int VOICE_CHAT_DEATH = 18; int VOICE_CHAT_POISONED = 19; int VOICE_CHAT_SPELLFAILED = 20; int VOICE_CHAT_WEAPONSUCKS = 21; int VOICE_CHAT_FOLLOWME = 22; int VOICE_CHAT_LOOKHERE = 23; int VOICE_CHAT_GROUP = 24; int VOICE_CHAT_MOVEOVER = 25; int VOICE_CHAT_PICKLOCK = 26; int VOICE_CHAT_SEARCH = 27; int VOICE_CHAT_HIDE = 28; int VOICE_CHAT_CANDO = 29; int VOICE_CHAT_CANTDO = 30; int VOICE_CHAT_TASKCOMPLETE = 31; int VOICE_CHAT_ENCUMBERED = 32; int VOICE_CHAT_SELECTED = 33; int VOICE_CHAT_HELLO = 34; int VOICE_CHAT_YES = 35; int VOICE_CHAT_NO = 36; int VOICE_CHAT_STOP = 37; int VOICE_CHAT_REST = 38; int VOICE_CHAT_BORED = 39; int VOICE_CHAT_GOODBYE = 40; int VOICE_CHAT_THANKS = 41; int VOICE_CHAT_LAUGH = 42; int VOICE_CHAT_CUSS = 43; int VOICE_CHAT_CHEER = 44; int VOICE_CHAT_TALKTOME = 45; int VOICE_CHAT_GOODIDEA = 46; int VOICE_CHAT_BADIDEA = 47; int VOICE_CHAT_THREATEN = 48; * string sTag is the tag of the creature that you want to perform the voice chat. By default, this creature is the owner of the conversation. See ginc_param_const->GetTarget() for more information. ** Not all sound sets have mappings to all the voice chats! ** If you request a voice chat ID that isn't valid for the target's sound set, no sound will play and you WILL NOT receive any feedback notifying you that the ID is invalid. As a general rule, all PC and companion sound sets will contain mappings to all the voice chats. Other sound sets may contain mappings to an attack, battle, pain, and death voice chat, at minimum. */ //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: Brian Fox //:: Created on: 9/6/06 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_param_const" void main( int nVoiceChat, string sTag ) { object oTarget = GetTarget( sTag ); if ( GetIsObjectValid(oTarget) ) { PlayVoiceChat( nVoiceChat, oTarget ); } else { PrettyError( "ga_play_voice_chat ERROR: " + sTag + " is not a valid object!" ); } } // ga_reequip_all_items /* re-equips all "remembered" items. */ // ChazM 6/27/06 #include "ginc_param_const" #include "ginc_item" void main(string sTarget) { object oOwner = GetTarget(sTarget); RestoreEquippedItems(oOwner, TRUE); } // ga_remember_equipped /* This script marks the equipped items so that they can later be restored. Parameters: string sCreature = Tag of object giving items. Default is PC. (Must be creature) */ // ChazM 3/15/06 #include "ginc_item" #include "ginc_param_const" void main(string sCreature) { object oCreature = GetTarget(sCreature, TARGET_PC); PrettyDebug ("sCreature = " + GetName(oCreature)); RememberEquippedItems(oCreature); } // ga_remove_comp(string sHenchmanTag) /* This script removes a henchman from the party. Parameters: string sTarget = Tag of the henchman to remove. If blank, remove dialog OWNER. If NPC is not a henchman of the PC, do nothing. */ // ChazM 4/14/05 // BMA 4/28/05 // ChazM 8/3/05 - use RemoveHenchmanByTag() // EPF 11/30/05 - making compatible with companions. #include "ginc_companion" #include "ginc_param_const" void main(string sCompanionTag) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oCompanion = GetTarget(sCompanionTag); string sRosterTag = GetRosterNameFromObject(oCompanion); if(IsHenchman(oCompanion, oPC)) { RemoveHenchmanByTag(oPC, sCompanionTag); } else { RemoveRosterMemberFromParty(sRosterTag, oPC); } } // ga_remove_feat /* This removes a feat from a creature, player or players. sTarg = The creature to remove the feat from. If blank, remove from PC nFeat = The number of the feat. See nwscript.nss for a list of feats. bAllPCs = If set to 1 it removes the feat to from the PCs (MP only). */ // TDE 3/4/06 void main(string sTarg, int nFeat, int bAllPCs) { object oTarg; if ( sTarg == "" ) { if ( !bAllPCs ) FeatRemove(GetPCSpeaker(), nFeat); else { oTarg = GetFirstPC(); while(GetIsObjectValid(oTarg)) { FeatRemove(oTarg, nFeat); oTarg = GetNextPC(); } } } else { oTarg = GetObjectByTag(sTarg); FeatRemove(oTarg, nFeat); } } // ga_replace_comp(string sCompToRemove, string sCompToAdd) // // replace companion with tag sCompToRemove with companion with tag sCompToAdd // // EPF 6/14/05 // ChazM 8/3/05 // EPF 11/30/05 -- fixing to work with companions #include "ginc_param_const" #include "ginc_companion" void main(string sCompToRemove, string sCompToAdd) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); string sRosterToAdd = GetRosterNameFromObject(GetTarget(sCompToAdd)); string sRosterToRemove = GetRosterNameFromObject(GetTarget(sCompToRemove)); RemoveRosterMemberFromParty(sRosterToRemove, oPC); AddRosterMemberToParty(sRosterToAdd, oPC); } // ga_reputation /* This adjusts the reputation of the calling player nActLevel = How noble or ignoble was the act from +4 (Idolized) to -4 (Vilified) nRepOver = This overides the reputation to the given value (DANGER!) */ // FAB 10/12/04 void main(int nActLevel, int nRepOver) { string sActLevel; int nRepLevel; // This is the reputation level of the PC right now int nRepValue; // The straight Reputation Score string sRepDelta; // How much the reputation will change int nRepDelta; // How much the reputation will change int nRepShift; // Used for shifting reputation by a set amount object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); // CHECK REPUTATION OVERRIDE - apply if set and then bail out of the script if ( nRepOver != 0 ) { SetLocalInt( oPC,"Player's Reputation",nRepOver ); return; } // Determines the act level for the 2DA check switch (nActLevel) { case -4: // Vilified Act sActLevel = "Vilified"; break; case -3: // Loathed Act sActLevel = "Loathed"; break; case -2: // Disliked Act sActLevel = "Disliked"; break; case -1: // Unwelcome Act sActLevel = "Unwelcome"; break; case 1: // Known Act sActLevel = "Known"; break; case 2: // Liked Act sActLevel = "Liked"; break; case 3: // Honored Act sActLevel = "Honored"; break; case 4: // Idolized Act sActLevel = "Idolized"; break; } //int nRepLevel; // This is the reputation level of the PC right now // Look at the PC's current rep to see where they are on the table nRepValue = GetLocalInt( oPC,"Player's Reputation" ); if ( nRepValue <= -110 ) nRepLevel = 8; else if ( nRepValue <= -80 ) nRepLevel = 7; else if ( nRepValue <= -50 ) nRepLevel = 6; else if ( nRepValue <= -25 ) nRepLevel = 5; else if ( nRepValue <= 24 ) nRepLevel = 4; else if ( nRepValue <= 49 ) nRepLevel = 3; else if ( nRepValue <= 79 ) nRepLevel = 2; else if ( nRepValue <= 109 ) nRepLevel = 1; else nRepLevel = 0; sRepDelta = Get2DAString( "Reputation",sActLevel,nRepLevel ); // This is an alignment shift - so deal with it appropriately if ( GetStringLeft(sRepDelta,2) == "S:" ) { nRepShift = StringToInt( GetStringRight( sRepDelta,GetStringLength(sRepDelta)-2 ) ); switch ( nRepShift ) { case -2: // Shift reputation to Disliked SetLocalInt( oPC,"Player's Reputation",-65 ); return; break; case -1: // Shift reputation to Unwelcome SetLocalInt( oPC,"Player's Reputation",-38 ); return; break; case 0: // Shift reputation to Neutral SetLocalInt( oPC,"Player's Reputation",0 ); return; break; case 1: // Shift reputation to Known SetLocalInt( oPC,"Player's Reputation",38 ); return; break; case 2: // Shift reputation to Liked SetLocalInt( oPC,"Player's Reputation",65 ); return; break; case 3: // Shift reputation to Honored SetLocalInt( oPC,"Player's Reputation",92 ); return; break; } } nRepDelta = StringToInt( sRepDelta ); SetLocalInt( oPC,"Player's Reputation",nRepValue + nRepDelta ); } // ga_reset_level( string sCreature, int bUseXPMods ) /* Resets creature to PCs average experience level using its current level-up package. Creature is also force rested ( full heal, spells refreshed ). Parameters: string sCreature = Tag of creature int bUseXPMods = If TRUE, XP modifiers will be applied before the experience is awarded */ // BMA-OEI 5/08/06 // BMA-OEI 8/09/06 -- Added GetPCAverageXP(), ForceRest() #include "ginc_debug" #include "ginc_misc" void main( string sCreature, int bUseXPMods ) { object oCreature = GetObjectByTag( sCreature ); if ( GetIsObjectValid( oCreature ) == FALSE ) { PrettyError( "ga_reset_level: object '" + sCreature + "' is invalid!" ); } int nXP = GetPCAverageXP(); ResetCreatureLevelForXP( oCreature, nXP, bUseXPMods ); ForceRest( oCreature ); } // ga_reset_level_by_xp( string sCreature, int nXP, int bUseXPMods ) /* Resets creature to level 0, awards nXP experience and auto-levels to the highest level allowed based on its current level-up package. Parameters: string sCreature = Tag of creature int nXP = Experience to award int bUseXPMods = If TRUE, XP modifiers will be applied before the experience is awarded */ // BMA-OEI 5/08/06 #include "ginc_debug" void main( string sCreature, int nXP, int bUseXPMods ) { object oCreature = GetObjectByTag( sCreature ); if ( GetIsObjectValid( oCreature ) == FALSE ) { PrettyError( "ga_reset_level_by_xp: object '" + sCreature + "' is invalid!" ); } ResetCreatureLevelForXP( oCreature, nXP, bUseXPMods ); } //ga_restoration // "casts" greater restoration on the target. // Parameter breakdown: // sTarget - tag of the creature to restore. GetTarget() parameters can be used, like $PC_SPEAKER or $OWNER // bFactionWide - if 1, the entire faction of sTarget gets restored as well. This Can restore the entire PC party, // which include companions and MP members. // bGroupWide - if 1, the entire group of the target is healed (if you are using ginc_group) // bSupressVFX - if 1, the visual effect of restoration in not played on those restored. In case you want to sly it. // DBR 8/25/06 #include "ginc_param_const" #include "ginc_group" void RestoreCreature(object oCreature, int bSupressVFX); void main(string sTarget, int bFactionWide, int bGroupWide, int bSupressVFX) { object oTarget = GetTarget(sTarget); if (!GetIsObjectValid(oTarget)) return; if (bFactionWide) { object oFactionMember = GetFirstFactionMember(oTarget,FALSE); while (GetIsObjectValid(oFactionMember)) { if (oFactionMember!=oTarget) RestoreCreature(oFactionMember,bSupressVFX); oFactionMember=GetNextFactionMember(oTarget,FALSE); } } if (bGroupWide) { string sGroup = GetGroupName(oTarget); object oGroupMember = GetFirstInGroup(sGroup); while (GetIsObjectValid(oGroupMember)) { if (oGroupMember!=oTarget) RestoreCreature(oGroupMember,bSupressVFX); oGroupMember = GetNextInGroup(sGroup); } } RestoreCreature(oTarget,bSupressVFX); } void RestoreCreature(object oCreature, int bSupressVFX) { //Declare major variables effect eVisual = EffectVisualEffect(VFX_IMP_RESTORATION_GREATER); effect eBad = GetFirstEffect(oCreature); //Search for negative effects while(GetIsEffectValid(eBad)) { if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE || GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS || GetEffectType(eBad) == EFFECT_TYPE_DEAF || GetEffectType(eBad) == EFFECT_TYPE_CURSE || GetEffectType(eBad) == EFFECT_TYPE_DISEASE || GetEffectType(eBad) == EFFECT_TYPE_POISON || GetEffectType(eBad) == EFFECT_TYPE_PARALYZE || GetEffectType(eBad) == EFFECT_TYPE_CHARMED || GetEffectType(eBad) == EFFECT_TYPE_DOMINATED || GetEffectType(eBad) == EFFECT_TYPE_DAZED || GetEffectType(eBad) == EFFECT_TYPE_CONFUSED || GetEffectType(eBad) == EFFECT_TYPE_FRIGHTENED || GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL || GetEffectType(eBad) == EFFECT_TYPE_PARALYZE || GetEffectType(eBad) == EFFECT_TYPE_SLOW || GetEffectType(eBad) == EFFECT_TYPE_STUNNED) { //Remove effect if it is negative. //if(!GetIsSupernaturalCurse(eBad)) // HOTU-SPECIFIC RemoveEffect(oCreature, eBad); eBad = GetFirstEffect(oCreature); } else eBad = GetNextEffect(oCreature); } if(GetRacialType(oCreature) != RACIAL_TYPE_UNDEAD) { //Apply the VFX impact and effects int nHeal = GetMaxHitPoints(oCreature) - GetCurrentHitPoints(oCreature); effect eHeal = EffectHeal(nHeal); ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oCreature); } //Fire cast spell at event for the specified target SignalEvent(oCreature, EventSpellCastAt(OBJECT_SELF, SPELL_GREATER_RESTORATION, FALSE)); if (!bSupressVFX) ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oCreature); } // ga_restore_equipped /* This script restores the equipped items that were previously marked with ga_remember_equipped. Parameters: string sCreature = Tag of object giving items. Default is PC. (Must be creature) */ // ChazM 3/15/06 #include "ginc_item" #include "ginc_param_const" void main(string sCreature) { object oCreature = GetTarget(sCreature, TARGET_PC); PrettyDebug ("sCreature = " + GetName(oCreature)); RestoreEquippedItems(oCreature); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_roster_add.nss //:: //:: Add creature by template to global roster. //:: //:: Parameters: //:: string sRosterName = 10-character name to reference in other //:: roster or party functions. //:: string sTemplate = Creature template to add to roster //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: Ben Ma //:: Created on: 10-25-05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_debug" void main(string sRosterName, string sTemplate) { int bResult = AddRosterMemberByTemplate(sRosterName, sTemplate); if (bResult == TRUE) { PrettyMessage("ga_roster_add: successfully added " + sRosterName + " (" + sTemplate + ")"); } else { PrettyError( "ga_roster_add: failed to add " + sRosterName + " (" + sTemplate + ")"); } } //ga_roster_add_blueprint /* //RWT-OEI 09/12/05 //Adds a NPC to the global roster of NPCs available to be added to //a player's party. Roster Name is a 10-character name used to reference //that NPC in other Roster related functions. //The template is the blueprint to use to create the NPC for the first //time. The NPC will not appear in the game world, but will be in the //Roster. Returns false on any error int AddRosterMemberByTemplate( string sRosterName, string sTemplate ); */ // ChazM 12/2/05 void main( string sRosterName, string sTemplate ) { int bResult = AddRosterMemberByTemplate(sRosterName, sTemplate); } //ga_roster_add_object /* //RWT-OEI 09/12/05 //Adds a NPC to the global roster of NPCs available to be added to //a player's party. Roster Name is a 10-character name used to //reference that NPC in other Roster related functions. //The NPC will be left in the game world, but will now exist //in the roster as well. //Returns false on any error int AddRosterMemberByCharacter( string sRosterName, object oCharacter ); */ // ChazM 12/2/05 #include "ginc_param_const" void main(string sRosterName, string sTarget) { object oCharacter = GetTarget(sTarget, TARGET_OWNER); int bResult = AddRosterMemberByCharacter(sRosterName, oCharacter); } // ga_roster_campaignnpc /* //RWT-OEI 09/29/05 //This function flags a Roster Member as being a Campaign NPC //Campaign NPCs are NPCs that are saved to the roster to make them //persist across modules, but will not appear on the Roster Member //Select Screen on clients as NPCs available for adding to the party. //Note that scripts can still add and remove Campaign NPCs to the party, //but the client will never be able to add them via the UI //Returns false if it was unable to find the Roster Member to set them //as a campaign NPC */ // BMA 02/27/06 void main( string sRosterName, int nCampaignNPC ) { int bResult = SetIsRosterMemberCampaignNPC(sRosterName, nCampaignNPC); } //ga_roster_despawn /* //RWT-OEI 09/15/05 //Despawn Roster Member //This function removes the Roster Member from the game after saving them //out so that any changes will be preserved. This is the matching function //to SpawnRosterMember() and in general should be the only script function //used to remove Party Member NPCs from the game world. int DespawnRosterMember( string sRosterName ); */ // ChazM 12/2/05 #include "ginc_param_const" void main(string sRosterName) { int bResult = DespawnRosterMember(sRosterName); } // ga_roster_despawn_all( int bExcludeParty ) /* Despawn all roster members, option to exclude members in PC party */ // BMA-OEI 7/28/06 #include "ginc_companion" void main( int bExcludeParty ) { DespawnAllRosterMembers( bExcludeParty ); } //ga_roster_gui_screen /* Pulls up the character selection GUI screen fot the PC Speaker DisplyGuiScreen( oPlayer, sScreenName, bModal) */ // ChazM 12/13/05 void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); DisplayGuiScreen( oPC, "SCRIPT_SCREEN_PARTYSELECT", TRUE ); } //ga_roster_party_add /* add roster party member to PC Speaker's party //RWT-OEI 09/15/05 //This function will add a Roster Member to the same party that the //player character object passed in belongs to. Note that if the //Roster Member is already in another party, this function will not //work. They must be removed from the other party first. You can check //for this condition with the GetIsRosterMemberAvailable() function. //If the Roster Member is Available, then they can be added to the party. //Also, if the RosterMember already exists somewhere in the module, //the RosterMember will be warped to be near the player character. If //the RosterMember does not exist yet, they will be loaded into the module //exactly as they were when they were last saved out. //Returns true on success int AddRosterMemberToParty( string sRosterName, object oPC ); */ // ChazM 12/2/05 // ChazM 12/13/05 - just does an add. #include "ginc_debug" void main(string sRosterName) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); int bResult = AddRosterMemberToParty(sRosterName, oPC); } //ga_roster_party_remove /* //RWT-OEI 09/19/05 //This function removes a roster member from the party. It does not //despawn the roster member or save the roster member's state. //Couple with DespawnRosterMember() if you need to remove the roster //member from the area or save their current state void RemoveRosterMemberFromParty( string sRosterName, object oPC ); */ // ChazM 12/2/05 #include "ginc_param_const" void main(string sRosterName, string sTarget) { object oTarget = GetTarget(sTarget, TARGET_PC); RemoveRosterMemberFromParty(sRosterName, oTarget); } // ga_roster_party_remove_all( int bDespawnNPC, int bIgnoreSelectable ) /* Remove all selectable roster members from oPC's party Parameters: int bDespawnNPC = If 1, despawn after removing from party int bIgnoreSelectable = If 1, also remove non-Selectable roster members */ // BMA-OEI 9/06/06 #include "ginc_companion" void main( int bDespawnNPC, int bIgnoreSelectable ) { object oPC = GetPCSpeaker(); if ( GetIsObjectValid( oPC ) == FALSE ) { oPC = OBJECT_SELF; } RemoveRosterMembersFromParty( oPC, bDespawnNPC, bIgnoreSelectable ); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ga_roster_rem.nss //:: //:: Remove a NPC from roster list //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: BMA-OEI //:: Created on: 10/18/05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_roster" void main(string sMember) { TestRemoveRosterMember(sMember); } //ga_roster_remove /* //RWT-OEI 09/14/05 //Removes a NPC from the global roster of NPCs available to be added to //a player's party. Roster Name is the 'identifying name' that was given //to this NPC when it was added to the Roster. Returns TRUE if the NPC //was found and removed. False if the NPC was not found in the roster int RemoveRosterMember( string sRosterName ); */ // ChazM 12/2/05 void main( string sRosterName) { int bResult = RemoveRosterMember(sRosterName); } // ga_roster_selectable /* //RWT-OEI 09/14/05 //Sets the roster member as being selectable or not. Roster members //that are not selectable cannot be changed via the Party Selection //GUI on the client side, but can still be added/removed from a //party via script. Note that if a roster member is set as non-selectable //while they are currently in a party, they will remain in the party //and cannot be removed via the Party Selection GUI. //Returns FALSE if it was unable to locate the roster member int SetIsRosterMemberSelectable( string sRosterName, int bSelectable ); */ // ChazM 12/2/05 void main( string sRosterName, int bSelectable) { int bResult = SetIsRosterMemberSelectable(sRosterName, bSelectable); } //ga_roster_spawn /* //RWT-OEI 09/15/05 //Takes a roster name and script location and places an instance of the //NPC there if possible. If the NPC already exists somewhere in the //module, it will move that NPC to the given location. If the NPC does //not exist, it will spawn in a new instance of the NPC from the roster //and place them at the given location. The return value is //the object ID of the newly spawned NPC, or INVALID_OBJECT if there //was some error encountered object SpawnRosterMember( string sRosterName, location lLocation ); */ // ChazM 12/2/05 #include "ginc_param_const" void main(string sRosterName, string sTargetLocationTag) { object oLocationObject = GetTarget(sTargetLocationTag, TARGET_OWNER); location lLocation = GetLocation(oLocationObject); object oSpawn = SpawnRosterMember(sRosterName, lLocation); } //ga_roster_spawn_rand_loc /* creates a list of roster names randomly disbursed in a radius around a target */ // ChazM 12/5/05 #include "ginc_param_const" #include "ginc_math" void main(string sRosterNameList, string sTargetLocationTag, float fRadius) { int nPos = 0; string sRosterName = GetStringParam(sRosterNameList, nPos); object oLocationObject = GetTarget(sTargetLocationTag, TARGET_OWNER); location lLocation = GetLocation(oLocationObject); object oSpawn; location lRandLoc; while (sRosterName != "") { lRandLoc = GetNearbyLocation(lLocation, fRadius, 0.0f); oSpawn = SpawnRosterMember(sRosterName, lRandLoc); sRosterName = GetStringParam(sRosterNameList, ++nPos); } } // ga_scripthidden // // Show or Hide an NPC, using its ScriptHiddenProperty. // // sTag is the tag of the object to hide. The script will affect the nearest object of that tag. // If there is none in the current area, it will affect whatever's returned by GetObjectByTag(). // // If bHide is TRUE, the NPC will disappear, if not, the NPC will appear. // EPF 1/9/06 #include "ginc_misc" void main(string sTag, int bHide) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oTarget = GetNearestObjectByTag(sTag,oPC); if(!GetIsObjectValid(oTarget)) { oTarget = GetObjectByTag(sTag); } SetScriptHidden(oTarget,bHide); } // ga_set_animation_condition(int nFlag, int bState, string sTarget) /* Sets Animation Condition flag. See below for list of flags. Some flags should probably not be altered by this script. */ // ChazM 9/1/06 /* NW_ANIM_CONDITION (int)  Various flags relating to the animations played by ambient characters. const int NW_ANIM_FLAG_INITIALIZED = 0x00000001; // 1 const int NW_ANIM_FLAG_CONSTANT = 0x00000002; // 2 const int NW_ANIM_FLAG_CHATTER = 0x00000004; // 4 const int NW_ANIM_FLAG_IS_ACTIVE = 0x00000008; // 8 const int NW_ANIM_FLAG_IS_INTERACTING = 0x00000010; // 16 const int NW_ANIM_FLAG_IS_INSIDE = 0x00000020; // 32 const int NW_ANIM_FLAG_HAS_HOME = 0x00000040; // 64 const int NW_ANIM_FLAG_IS_TALKING = 0x00000080; // 128 const int NW_ANIM_FLAG_IS_MOBILE = 0x00000100; // 256 const int NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE = 0x00000200; // 512 const int NW_ANIM_FLAG_IS_CIVILIZED = 0x00000400; // 1024 const int NW_ANIM_FLAG_CLOSE_DOORS = 0x00001000; // 2048 */ #include "x0_i0_anims" #include "ginc_param_const" #include "ginc_debug" void main(int nFlag, int bState, string sTarget) { object oTarget = GetTarget(sTarget); int iAnim = GetLocalInt(oTarget, "NW_ANIM_CONDITION"); SetAnimationCondition(nFlag, bState, oTarget); int iNewAnim = GetLocalInt(oTarget, "NW_ANIM_CONDITION"); PrettyDebug (GetName(oTarget) + " NW_ANIM_CONDITION was = " + IntToString(iAnim) + " - now = " + IntToString(iNewAnim)); } // ga_set_associate_state(int nFlag, int bState, string sTarget) /* Sets Associate State flag. See below for list of flags. Some flags should probably not be altered by this script. */ // ChazM /* From x0_i0_assoc.nss: //Distance const int NW_ASC_DISTANCE_2_METERS = 0x00000001; 1 const int NW_ASC_DISTANCE_4_METERS = 0x00000002; 2 const int NW_ASC_DISTANCE_6_METERS = 0x00000004; 4 // Percentage of master's damage at which the // assoc will try to heal them. const int NW_ASC_HEAL_AT_75 = 0x00000008; 8 const int NW_ASC_HEAL_AT_50 = 0x00000010; 16 const int NW_ASC_HEAL_AT_25 = 0x00000020; 32 //Auto AI const int NW_ASC_AGGRESSIVE_BUFF = 0x00000040; 64 const int NW_ASC_AGGRESSIVE_SEARCH = 0x00000080; 128 const int NW_ASC_AGGRESSIVE_STEALTH = 0x00000100; 256 //Open Locks on master fail const int NW_ASC_RETRY_OPEN_LOCKS = 0x00000200; 512 //Casting power const int NW_ASC_OVERKIll_CASTING = 0x00000400; 1024 // GetMax Spell const int NW_ASC_POWER_CASTING = 0x00000800; 2048 // Get Double CR or max 4 casting const int NW_ASC_SCALED_CASTING = 0x00001000; 4096 // CR + 4; const int NW_ASC_USE_CUSTOM_DIALOGUE = 0x00002000; 8192 const int NW_ASC_DISARM_TRAPS = 0x00004000; 16384 const int NW_ASC_USE_RANGED_WEAPON = 0x00008000; 32768 // Playing Dead mode, used to make sure the associate is // not targeted while dying. const int NW_ASC_MODE_DYING = 0x00010000; 65536 //Guard Me Mode, Attack Nearest sets this to FALSE. const int NW_ASC_MODE_DEFEND_MASTER = 0x04000000; 67108864 //The Henchman will ignore move to object in their OnHeartbeat. //If this is set to FALSE then they are in follow mode. const int NW_ASC_MODE_STAND_GROUND = 0x08000000; 134217728 const int NW_ASC_MASTER_GONE = 0x10000000; 268435456 const int NW_ASC_MASTER_REVOKED = 0x20000000; 536870912 //Only busy if attempting to bash or pick a lock or dead const int NW_ASC_IS_BUSY = 0x40000000; 1073741824 */ #include "X0_I0_ASSOC" #include "ginc_param_const" void main(int nFlag, int bState, string sTarget) { object oAssoc = GetTarget(sTarget); SetAssociateState(nFlag, bState, oAssoc); } // ga_set_gflag /* Set GlobalFlagName as a global int w/ value 1. */ // ChazM 7/21/05 void main() { string sGlobalFlagName = GetLocalString(OBJECT_SELF, "GlobalFlagName"); if (sGlobalFlagName != "") SetGlobalInt(sGlobalFlagName, 1); } //ga_set_weapon_visibility // Conversation script wrapper for SetWeaponVisibility() command. // // sTarget - tag of creature to set weapon visibilty - default is conversation owner. // bVisible - 1 for always visible, 0 for always invisible, 4 to turn off the override. // nType - NOT CURRENTLY USED see nwscript.nss for more information, this is the nType parameter in SetWeaponVisibility() // bForWholeGroup - Sets weapon visibility for the whole group of sTarget. // bForWholeFaction - Sets weapon visibility for the whole faction of sTarget. // DBR 6/22/06 #include "ginc_param_const" #include "ginc_group" void main(string sTarget, int bVisible, int nType=0, int bForWholeGroup=0, int bForWholeFaction=0) { object oTarget = GetTarget(sTarget); object oMember; string sGroup; if (GetIsObjectValid(oTarget)) { SetWeaponVisibility(oTarget, bVisible, nType); if (bForWholeGroup) //Group-Wide { sGroup = GetGroupName(oTarget); oMember = GetFirstInGroup(sGroup); while (GetIsObjectValid(oMember)) { SetWeaponVisibility(oMember, bVisible, nType); oMember = GetNextInGroup(sGroup); } } if (bForWholeFaction) //Faction-Wide { oMember = GetFirstFactionMember(oTarget, FALSE); while (GetIsObjectValid(oMember)) { SetWeaponVisibility(oMember, bVisible, nType); oMember = GetNextFactionMember(oTarget,FALSE); } } } } // ga_set_wwp_controller /* Changes the waypoint set specified creature will walk. This overrides whatever the creature's tag is. sWalkWayPointsTag is the tag of the creature the waypoints are designed for, i.e. no prefix or suffix Note that walkwaypoints is interrupted by being in a conversation. Creature must use a script set that supports WWP to work long-term. */ // ChazM 7/9/06 // ChazM 7/9/06 - GetNextWalkWayPoint() calls a bunch of other stuff we don't want - used alt method. // ChazM 8/13/06 - simplified script #include "ginc_wp" #include "ginc_param_const" void UpdateWWPController(string sWalkWayPointsTag) { //SpawnScriptDebugger(); object oWWPController = SetWWPController(sWalkWayPointsTag); // This will get creature started now instead of waiting for the hearbeat following the end of the conversation. // Note: WalkWayPoints() won't do anything if called while creature is in a conversation. (WWP is desinged not to interrupt conversations). MoveToNextWaypoint(TRUE, TRUE); } void main(string sTarget, string sWalkWayPointsTag) { object oTarget = GetTarget(sTarget); AssignCommand(oTarget, UpdateWWPController(sWalkWayPointsTag)); } // ga_setbumpstate // Set the bumpable flag for sTarget. // nBumpState is defined as follows in nwscript.nss: // int BUMPSTATE_DEFAULT = 0; // int BUMPSTATE_BUMPABLE = 1; // int BUMPSTATE_UNBUMPABLE = 2; // EPF 8.2.06 #include "ginc_param_const" void main(string sTarget, int nBumpState) { object oTarget = GetTarget(sTarget); SetBumpState(oTarget, nBumpState); } // ga_setimmortal(string sTarget, int bImmortal) /* SetImmortal on target creature to bImmortal. Parameters: string sTarget = tag of target creature, if blank use OWNER int bImmortal = 0 for FALSE, else for TRUE */ // BMA-OEI 9/28/05 #include "ginc_param_const" #include "ginc_debug" void main(string sTarget, int bImmortal) { object oTarget = GetTarget(sTarget, TARGET_OWNER); if (GetIsObjectValid(oTarget) == TRUE) { if (bImmortal != 0) { bImmortal = TRUE; } else { bImmortal = FALSE; } SetImmortal(oTarget, bImmortal); } else { ErrorMessage("ga_setimmortal: " + sTarget + " not found!"); } } // ga_setplotflag(string sTarget, int bPlotFlag) /* SetPlotFlag on target object to bPlotFlag. Parameters: string sTarget = tag of target object, if blank use OWNER int bPlotFlag = 0 for FALSE, else for TRUE */ // BMA-OEI 9/28/05 #include "ginc_param_const" #include "ginc_debug" void main(string sTarget, int bPlotFlag) { object oTarget = GetTarget(sTarget, TARGET_OWNER); if (GetIsObjectValid(oTarget) == TRUE) { if (bPlotFlag != 0) { bPlotFlag = TRUE; } else { bPlotFlag = FALSE; } SetPlotFlag(oTarget, bPlotFlag); } else { ErrorMessage("ga_setplotflag: " + sTarget + " not found!"); } } // ga_setrecipes /* sets up all the recipes for creating magic items this can be run at any time prior to a PC using them in game. (module load might be good) Reference Info: see lexicon for constants: Home > Reference > Constants > SPELL_* Home > Reference > Constants > ITEM_PROPERTY_* specific constants available for most item properties: Home > Reference > Constants > IP_CONST_ABILITY_* ... IP_CONST_WEIGHTINCREASE_* */ // ChazM 12/15/05 // FAB 1/13/06 - Plugging in the materials, working on recipes // ChazM 1/31/06 - implementing in NWN2 // ChazM 2/1/06 - Reorganized/updated file. // ChazM 3/1/06 - Incorporated aditional recipes // TDE 3/4/06 - Added Gold Filigree Charm for summoning Mephasm in Crossroad Keep // ChazM 3/1/06 - Massaged new distillation recipes. // ChazM 3/23/06 - Updated all mold constants // ChazM 4/11/06 - Added Traps // ChazM 4/18/06 - globally replaced tag suffix list with item category constants, removed test recipes // TDE 6/8/06 - Added Infernal Focus recipes for bargaining with Mephasm in Crossroad Keep // ChazM 8/3/06 - Iron Golem Fragments now distill to Radiant Earth Essence // ChazM 8/14/06 - corrected 3 mold tags // ChazM 9/9/06 - minor constant changes // ChazM 9/10/06 - fixed dragon blood, fire beetle belly, removed unused test constants and commented out recipes // replaced old constant SPELL_RESIST_ELEMENTS with SPELL_RESIST_ENERGY // ChazM 9/10/06 - fixes from Annie for recipes: RING_DIVINE_POWER_2, RING_WIZARDRY_2, SCABBARD_KEEN_EDGES // ChazM 9/27/06 - Added WarMace, silver bastard sword, and silver falchion // ChazM 9/27/06 - Added SetUpAlchemyRecipes6() // ChazM 9/29/06 - Added SetUpStandardMetalItem(), added flails, weapon mold comments, removed double bladed sword mold // ChazM 9/29/06 - Added armor comments, removed duskwood breastplate mold and recipe, modified SetUpMundaneRecipes6() // ChazM 10/20/06 - Modified weapon and armor Haste effect recipes - replaced w/ ability to cast haste 3x/day // ChazM 11/9/06 - The charm and focus can be created using standard darkness or the warlock invocation darkness // ChazM 11/10/06 - fixed MEDALLION_THOUGHTS, armor Arrow Deflection, weapon Poison // ChazM 11/13/06 - fixed Invulnerable #include "ginc_crafting" // ================================================================================= // Constants // ================================================================================= // Tags of all Essences const string FIRE1 = "cft_ess_fire1"; const string FIRE2 = "cft_ess_fire2"; const string FIRE3 = "cft_ess_fire3"; const string FIRE4 = "cft_ess_fire4"; const string WATER1 = "cft_ess_water1"; const string WATER2 = "cft_ess_water2"; const string WATER3 = "cft_ess_water3"; const string WATER4 = "cft_ess_water4"; const string AIR1 = "cft_ess_air1"; const string AIR2 = "cft_ess_air2"; const string AIR3 = "cft_ess_air3"; const string AIR4 = "cft_ess_air4"; const string EARTH1 = "cft_ess_earth1"; const string EARTH2 = "cft_ess_earth2"; const string EARTH3 = "cft_ess_earth3"; const string EARTH4 = "cft_ess_earth4"; const string POWER1 = "cft_ess_power1"; const string POWER2 = "cft_ess_power2"; const string POWER3 = "cft_ess_power3"; const string POWER4 = "cft_ess_power4"; // Tags of all Gems const string BLOODSTONE = "cft_gem_01"; const string TOPAZ = "NW_IT_GEM010"; const string OBSIDIAN = "cft_gem_03"; const string SAPPHIRE = "NW_IT_GEM008"; const string FIRE_OPAL = "NW_IT_GEM009"; const string DIAMOND = "NW_IT_GEM005"; const string RUBY = "NW_IT_GEM006"; const string EMERALD = "NW_IT_GEM012"; const string CANARY_DIAMOND = "cft_gem_09"; const string STAR_SAPPHIRE = "cft_gem_10"; const string JACINTH = "cft_gem_11"; const string BLUE_DIAMOND = "cft_gem_12"; const string ROGUE_STONE = "cft_gem_13"; const string BELJURIL = "cft_gem_14"; const string KINGS_TEAR = "cft_gem_15"; const string GARNET = "NW_IT_GEM011"; // Tags of all Basic Crafting Materials const string HIDE_LEATHER = "n2_crft_hideleather"; const string HIDE_DRAGON = "n2_crft_hidedragon"; const string HIDE_SALAMANDER = "n2_crft_hidesalam"; const string HIDE_UMBER_HULK = "n2_crft_hideumber"; const string HIDE_WYVERN = "n2_crft_hidewyvern"; const string INGOT_IRON = "n2_crft_ingiron"; const string INGOT_ADAMANTINE = "n2_crft_ingadamant"; const string INGOT_COLD_IRON = "n2_crft_ingcldiron"; const string INGOT_DARKSTEEL = "n2_crft_ingdrksteel"; const string INGOT_MITHRAL = "n2_crft_ingmithral"; const string INGOT_SILVER = "n2_crft_ingsilver"; const string PLANK_WOOD = "n2_crft_plkwood"; const string PLANK_DUSKWOOD = "n2_crft_plkdskwood"; const string PLANK_ZALANTAR = "n2_crft_plkzalantar"; const string PLANK_SHEDERRAN = "n2_crft_plkshed"; // TDE: Added Gold Necklace for Gold Filigree Charm (used for summoning Mephasm in Crossroad Keep) const string GOLD_NECKLACE = "NW_IT_MNECK022"; // Tags of Wondrous Items (long list) const string BOOTS_STRIDING_2 = "NW_IT_MBOOTS006"; const string BOOTS_STRIDING_4 = "NW_IT_MBOOTS008"; const string BOOTS_STRIDING_6 = "X2_IT_MBOOTS006"; const string BOOTS_STRIDING_8 = "X2_IT_MBOOTS008"; const string AMULET_NATURAL_ARMOR_1 = "NW_IT_MNECK001"; const string AMULET_NATURAL_ARMOR_2 = "NW_IT_MNECK012"; const string AMULET_NATURAL_ARMOR_3 = "NW_IT_MNECK013"; const string AMULET_NATURAL_ARMOR_4 = "NW_IT_MNECK014"; const string AMULET_NATURAL_ARMOR_5 = "NW_IT_MNECK015"; const string BELT_FROST_GIANT_STRENGTH = "NW_IT_MBELT007"; const string BELT_STONE_GIANT_STRENGTH = "n2_it_mbelt001"; const string BELT_CLOUD_GIANT_STRENGTH = "X2_IT_MBELT001"; const string BOOTS_ELVENKIND = "NW_IT_MBOOTS002"; const string BOOTS_SPEED = "NW_IT_MBOOTS005"; const string BRACERS_ARMOR_1 = "NW_IT_MBRACER002"; const string BRACERS_ARMOR_2 = "NW_IT_MBRACER007"; const string BRACERS_ARMOR_3 = "NW_IT_MBRACER008"; const string BRACERS_ARMOR_4 = "NW_IT_MBRACER009"; const string BRACERS_ARMOR_5 = "NW_IT_MBRACER010"; const string BRACERS_ARMOR_6 = "X2_IT_MBRACER001"; const string BRACERS_ARMOR_7 = "X2_IT_MBRACER002"; const string BRACERS_ARMOR_8 = "X2_IT_MBRACER003"; const string BROOCH_SHIELDING = "X0_IT_MMEDMISC01"; const string NYMPH_CLOAK_2 = "NW_MAARCL092"; const string NYMPH_CLOAK_4 = "NW_MAARCL094"; const string NYMPH_CLOAK_6 = "X2_IT_MCLOAK008"; const string NYMPH_CLOAK_8 = "n2_it_mcloak001"; const string CLOAK_DISPLACEMENT = "X0_MAARCL032"; const string CLOAK_ELVENKIND = "NW_MAARCL057"; const string CLOAK_RESISTANCE_1 = "X0_MAARCL025"; const string CLOAK_RESISTANCE_2 = "X0_MAARCL026"; const string CLOAK_RESISTANCE_3 = "X0_MAARCL027"; const string CLOAK_RESISTANCE_4 = "X0_MAARCL028"; const string CLOAK_RESISTANCE_5 = "X0_MAARCL029"; //const string EYES_EAGLE = "X0_ARMHE005"; (no "Eyes" items) const string GAUNTLETS_OGRE_POWER = "NW_IT_MBRACER013"; const string GEM_SEEING = "X0_IT_MSMLMISC04"; const string BELT_AGILITY_2 = "nw_it_mbelt019"; const string BELT_AGILITY_4 = "nw_it_mbelt021"; const string BELT_AGILITY_6 = "X2_IT_MBELT004"; const string BELT_AGILITY_8 = "X2_IT_MBELT006"; //const string GOGGLES_MINUTE_SEEING = "X0_ARMHE007"; (no "Goggles" items) //const string GOGGLES_NIGHT = "X0_ARMHE008"; (no "Goggles" items) const string HEADBAND_INTELLECT_2 = "X0_ARMHE009"; const string HEADBAND_INTELLECT_4 = "X0_ARMHE010"; const string HEADBAND_INTELLECT_6 = "X0_ARMHE011"; const string HEADBAND_INTELLECT_8 = "n2_armhe001"; //const string HORN_GOODNESS = "X0_IT_MTHNMISC09"; (no horns) const string MANTLE_GREATER_SPELL_RESISTANCE = "X0_MAARCL034"; const string MEDALLION_THOUGHTS = "n2_it_mneck002"; const string RING_DIVINE_POWER_1 = "n2_it_mring006"; const string RING_DIVINE_POWER_2 = "n2_it_mring002"; const string RING_DIVINE_POWER_3 = "n2_it_mring003"; const string RING_DIVINE_POWER_4 = "n2_it_mring004"; const string RING_DIVINE_POWER_5 = "n2_it_mring005"; const string RING_WIZARDRY_1 = "n2_it_mring007"; const string RING_WIZARDRY_2 = "n2_it_mring008"; const string RING_WIZARDRY_3 = "n2_it_mring009"; const string RING_WIZARDRY_4 = "n2_it_mring010"; const string RING_WIZARDRY_5 = "n2_it_mring011"; const string AMULET_HEALTH = "NW_IT_MNECK036"; const string LESSER_AMULET_HEALTH = "NW_IT_MNECK035"; const string GREATER_AMULET_HEALTH = "NW_IT_MNECK037"; const string PERIAPT_WISDOM_2 = "NW_IT_MNECK008"; const string PERIAPT_WISDOM_4 = "NW_IT_MNECK010"; const string PERIAPT_WISDOM_6 = "X2_IT_MNECK006"; const string PERIAPT_WISDOM_8 = "X2_IT_MNECK008"; const string ROBE_ARCHMAGE = "n2_mcloth001"; const string SCABBARD_KEEN_EDGES = "n2_it_mmidmisc01"; const string SCARAB_GREATER_PROTECTION = "X0_IT_MNECK003"; // TDE: Added Gold Filigree Charm (used for summoning Mephasm in Crossroad Keep) const string MEPHASM_CHARM = "31_mephasm_charm"; // TDE: Added Infernal Focus (used for bargaining with Mephasm in Crossroad Keep) const string MEPHASM_FOCUS = "31_mephasm_focus"; // Tags of all Craft Weapon and Armor Molds // Missile Weapons const string MOLD_WPN_BWXH = "n2_crft_mold_bwxh"; // Heavy Crossbow const string MOLD_WPN_BWXL = "n2_crft_mold_bwxl"; // Light Crossbow const string MOLD_WPN_BWLN = "n2_crft_mold_bwln"; // Longbow const string MOLD_WPN_BWSH = "n2_crft_mold_bwsh"; // Shortbow // Melee Weapons const string MOLD_WPN_SWBS = "n2_crft_mold_swbs"; // Bastard Sword const string MOLD_WPN_AXBT = "n2_crft_mold_axbt"; // Battle Axe const string MOLD_WPN_BLCL = "n2_crft_mold_blcl"; // Club const string MOLD_WPN_SWDG = "n2_crft_mold_swdg"; // Dagger const string MOLD_WPN_AXDV = "n2_crft_mold_axdv"; // Dwarvish Axe const string MOLD_WPN_SWFL = "n2_crft_mold_swfl"; // Falchion const string MOLD_WPN_FLAIL = "n2_crft_mold_blfl"; // Flail const string MOLD_WPN_AXGR = "n2_crft_mold_axgr"; // Greataxe const string MOLD_WPN_SWGS = "n2_crft_mold_swgs"; // Great Sword const string MOLD_WPN_PLHB = "n2_crft_mold_plhb"; // Halberd const string MOLD_WPN_BLHL = "n2_crft_mold_blhl"; // Light Hammer const string MOLD_WPN_AXHN = "n2_crft_mold_axhn"; // Hand Axe const string MOLD_WPN_SPKA = "n2_crft_mold_spka"; // Kama const string MOLD_WPN_SWKA = "n2_crft_mold_swka"; // Katana const string MOLD_WPN_SPKU = "n2_crft_mold_spku"; // Kukri const string MOLD_WPN_SWLS = "n2_crft_mold_swls"; // Long Sword const string MOLD_WPN_BLML = "n2_crft_mold_blml"; // Mace const string MOLD_WPN_BLMS = "n2_crft_mold_blms"; // Morningstar const string MOLD_WPN_DBQS = "n2_crft_mold_dbqs"; // Quarterstaff const string MOLD_WPN_SWRP = "n2_crft_mold_swrp"; // Rapier const string MOLD_WPN_SWSC = "n2_crft_mold_swsc"; // Scimitar const string MOLD_WPN_PLSC = "n2_crft_mold_plsc"; // Scythe const string MOLD_WPN_SWSS = "n2_crft_mold_swss"; // Short Sword const string MOLD_WPN_SPSC = "n2_crft_mold_spsc"; // Sickle const string MOLD_WPN_PLSS = "n2_crft_mold_plss"; // Spear //const string MOLD_WPN_SWDB = "n2_crft_mold_swdb"; // Double bladed sword const string MOLD_WPN_BLHW = "n2_crft_mold_blhw"; // Warhammer const string MOLD_WPN_WARMACE = "n2_crft_mold_bldm"; // Warmace // Armor const string MOLD_ARM_LTPD = "n2_crft_mold_ltpd"; // Padded Armor const string MOLD_ARM_LTLT = "n2_crft_mold_ltlt"; // Leather Armor const string MOLD_ARM_LTSL = "n2_crft_mold_ltsl"; // Studded Leather Armor const string MOLD_ARM_LTCS = "n2_crft_mold_ltcs"; // Chain Shirt const string MOLD_ARM_MDHD = "n2_crft_mold_mdhd"; // Hide Armor const string MOLD_ARM_MDSM = "n2_crft_mold_mdsm"; // Scale Mail const string MOLD_ARM_MDCM = "n2_crft_mold_mdcm"; // Chainmail const string MOLD_ARM_MDBP = "n2_crft_mold_mdbp"; // Breastplate const string MOLD_ARM_HVBM = "n2_crft_mold_hvbm"; // Banded Mail const string MOLD_ARM_HVHP = "n2_crft_mold_hvhp"; // Half Plate const string MOLD_ARM_HVFP = "n2_crft_mold_hvfp"; // Full Plate // Shields const string MOLD_ARM_SHLT = "n2_crft_mold_shlt"; // Light Shield const string MOLD_ARM_SHHV = "n2_crft_mold_shhv"; // Heavy Shield const string MOLD_ARM_SHTW = "n2_crft_mold_shtw"; // Tower Shield // Tags of all Crafted Weapons const string WPN_AXBT_ADA = "mst_axbt_ada_3"; const string WPN_AXBT_CLD = "mst_axbt_cld_3"; const string WPN_AXBT_DRK = "mst_axbt_drk_3"; const string WPN_AXBT_IRN = "nw_waxbt001"; const string WPN_AXBT_MTH = "mst_axbt_mth_3"; const string WPN_AXBT_SLV = "mst_axbt_slv_3"; const string WPN_AXDV_ADA = "mst_axdv_ada_3"; const string WPN_AXDV_CLD = "mst_axdv_cld_3"; const string WPN_AXDV_DRK = "mst_axdv_drk_3"; const string WPN_AXDV_IRN = "x2_wdwraxe001"; const string WPN_AXDV_MTH = "mst_axdv_mth_3"; const string WPN_AXDV_SLV = "mst_axdv_slv_3"; const string WPN_AXGR_ADA = "mst_axgr_ada_3"; const string WPN_AXGR_CLD = "mst_axgr_cld_3"; const string WPN_AXGR_DRK = "mst_axgr_drk_3"; const string WPN_AXGR_IRN = "nw_waxgr001"; const string WPN_AXGR_MTH = "mst_axgr_mth_3"; const string WPN_AXGR_SLV = "mst_axgr_slv_3"; const string WPN_AXHN_ADA = "mst_axhn_ada_3"; const string WPN_AXHN_CLD = "mst_axhn_cld_3"; const string WPN_AXHN_DRK = "mst_axhn_drk_3"; const string WPN_AXHN_IRN = "nw_waxhn001"; const string WPN_AXHN_MTH = "mst_axhn_mth_3"; const string WPN_AXHN_SLV = "mst_axhn_slv_3"; const string WPN_BLCL_DSK = "mst_blcl_dsk_3"; const string WPN_BLCL_FWD = "mst_blcl_fwd_3"; const string WPN_BLCL_LAN = "nw_wblcl001"; const string WPN_BLCL_ZAL = "mst_blcl_zal_3"; const string WPN_BLHL_ADA = "mst_blhl_ada_3"; const string WPN_BLHL_CLD = "mst_blhl_cld_3"; const string WPN_BLHL_DRK = "mst_blhl_drk_3"; const string WPN_BLHL_IRN = "nw_wblhl001"; const string WPN_BLHL_MTH = "mst_blhl_mth_3"; const string WPN_BLHL_SLV = "mst_blhl_slv_3"; const string WPN_BLHW_ADA = "mst_blhw_ada_3"; const string WPN_BLHW_CLD = "mst_blhw_cld_3"; const string WPN_BLHW_DRK = "mst_blhw_drk_3"; const string WPN_BLHW_IRN = "nw_wblhw001"; const string WPN_BLHW_MTH = "mst_blhw_mth_3"; const string WPN_BLHW_SLV = "mst_blhw_slv_3"; const string WPN_BLML_ADA = "mst_blml_ada_3"; const string WPN_BLML_CLD = "mst_blml_cld_3"; const string WPN_BLML_DRK = "mst_blml_drk_3"; const string WPN_BLML_IRN = "nw_wblml001"; const string WPN_BLML_MTH = "mst_blml_mth_3"; const string WPN_BLML_SLV = "mst_blml_slv_3"; const string WPN_BLMS_ADA = "mst_blms_ada_3"; const string WPN_BLMS_CLD = "mst_blms_cld_3"; const string WPN_BLMS_DRK = "mst_blms_drk_3"; const string WPN_BLMS_IRN = "nw_wblms001"; const string WPN_BLMS_MTH = "mst_blms_mth_3"; const string WPN_BLMS_SLV = "mst_blms_slv_3"; const string WPN_BWLN_DSK = "mwr_bwln_dsk_4"; const string WPN_BWLN_FWD = "mwr_bwln_fwd_3"; const string WPN_BWLN_LAN = "nw_wbwln001"; const string WPN_BWLN_SHD = "mwr_bwln_shd_3"; const string WPN_BWLN_ZAL = "mwr_bwln_zal_3"; const string WPN_BWSH_DSK = "mwr_bwsh_dsk_4"; const string WPN_BWSH_FWD = "mwr_bwsh_fwd_3"; const string WPN_BWSH_LAN = "nw_wbwsh001"; const string WPN_BWSH_SHD = "mwr_bwsh_shd_3"; const string WPN_BWSH_ZAL = "mwr_bwsh_zal_3"; const string WPN_BWXH_DSK = "mwr_bwxh_dsk_4"; const string WPN_BWXH_FWD = "mwr_bwxh_fwd_4"; const string WPN_BWXH_LAN = "nw_wbwxh001"; const string WPN_BWXH_SHD = "mwr_bwxh_shd_3"; const string WPN_BWXH_ZAL = "mwr_bwxh_zal_3"; const string WPN_BWXL_DSK = "mwr_bwxl_dsk_4"; const string WPN_BWXL_FWD = "mwr_bwxl_fwd_3"; const string WPN_BWXL_LAN = "nw_wbwxl001"; const string WPN_BWXL_SHD = "mwr_bwxl_shd_3"; const string WPN_BWXL_ZAL = "mwr_bwxl_zal_3"; const string WPN_DBQS_DSK = "mst_dbqs_dsk_3"; const string WPN_DBQS_FWD = "mst_dbqs_fwd_3"; const string WPN_DBQS_LAN = "nw_wdbqs001"; const string WPN_DBQS_ZAL = "mst_dbqs_zal_3"; const string WPN_PLHB_ADA = "mst_plhb_ada_3"; const string WPN_PLHB_CLD = "mst_plhb_cld_3"; const string WPN_PLHB_DRK = "mst_plhb_drk_3"; const string WPN_PLHB_IRN = "nw_wplhb001"; const string WPN_PLHB_MTH = "mst_plhb_mth_3"; const string WPN_PLHB_SLV = "mst_plhb_slv_3"; const string WPN_PLSC_ADA = "mst_plsc_ada_3"; const string WPN_PLSC_CLD = "mst_plsc_cld_3"; const string WPN_PLSC_DRK = "mst_plsc_drk_3"; const string WPN_PLSC_IRN = "nw_wplsc001"; const string WPN_PLSC_MTH = "mst_plsc_mth_3"; const string WPN_PLSC_SLV = "mst_plsc_slv_3"; const string WPN_PLSS_DSK = "mst_plss_dsk_3"; const string WPN_PLSS_FWD = "mst_plss_fwd_3"; const string WPN_PLSS_LAN = "nw_wplss001"; const string WPN_PLSS_ZAL = "mst_plss_zal_3"; const string WPN_SPKA_ADA = "mst_spka_ada_3"; const string WPN_SPKA_CLD = "mst_spka_cld_3"; const string WPN_SPKA_DRK = "mst_spka_drk_3"; const string WPN_SPKA_IRN = "nw_wspka001"; const string WPN_SPKA_MTH = "mst_spka_mth_3"; const string WPN_SPKA_SLV = "mst_spka_slv_3"; const string WPN_SPKU_ADA = "mst_spku_ada_3"; const string WPN_SPKU_CLD = "mst_spku_cld_3"; const string WPN_SPKU_DRK = "mst_spku_drk_3"; const string WPN_SPKU_IRN = "nw_wspku001"; const string WPN_SPKU_MTH = "mst_spku_mth_3"; const string WPN_SPKU_SLV = "mst_spku_slv_3"; const string WPN_SPSC_ADA = "mst_spsc_ada_3"; const string WPN_SPSC_CLD = "mst_spsc_cld_3"; const string WPN_SPSC_DRK = "mst_spsc_drk_3"; const string WPN_SPSC_IRN = "nw_wspsc001"; const string WPN_SPSC_MTH = "mst_spsc_mth_3"; const string WPN_SPSC_SLV = "mst_spsc_slv_3"; const string WPN_SWBS_ADA = "mst_swbs_ada_3"; const string WPN_SWBS_CLD = "mst_swbs_cld_3"; const string WPN_SWBS_DRK = "mst_swbs_drk_3"; const string WPN_SWBS_IRN = "nw_wswbs001"; const string WPN_SWBS_MTH = "mst_swbs_mth_3"; const string WPN_SWBS_SLV = "mst_swbs_slv_3"; const string WPN_SWDG_ADA = "mst_swdg_ada_3"; const string WPN_SWDG_CLD = "mst_swdg_cld_3"; const string WPN_SWDG_DRK = "mst_swdg_drk_3"; const string WPN_SWDG_IRN = "nw_wswdg001"; const string WPN_SWDG_MTH = "mst_swdg_mth_3"; const string WPN_SWDG_SLV = "mst_swdg_slv_3"; const string WPN_SWFL_ADA = "mst_swfl_ada_3"; const string WPN_SWFL_CLD = "mst_swfl_cld_3"; const string WPN_SWFL_DRK = "mst_swfl_drk_3"; const string WPN_SWFL_IRN = "n2_wswfl001"; const string WPN_SWFL_MTH = "mst_swfl_mth_3"; const string WPN_SWFL_SLV = "mst_swfl_slv_3"; const string WPN_SWGS_ADA = "mst_swgs_ada_3"; const string WPN_SWGS_CLD = "mst_swgs_cld_3"; const string WPN_SWGS_DRK = "mst_swgs_drk_3"; const string WPN_SWGS_IRN = "nw_wswgs001"; const string WPN_SWGS_MTH = "mst_swgs_mth_3"; const string WPN_SWGS_SLV = "mst_swgs_slv_3"; const string WPN_SWKA_ADA = "mst_swka_ada_3"; const string WPN_SWKA_CLD = "mst_swka_cld_3"; const string WPN_SWKA_DRK = "mst_swka_drk_3"; const string WPN_SWKA_IRN = "nw_wswka001"; const string WPN_SWKA_MTH = "mst_swka_mth_3"; const string WPN_SWKA_SLV = "mst_swka_slv_3"; const string WPN_SWLS_ADA = "mst_swls_ada_3"; const string WPN_SWLS_CLD = "mst_swls_cld_3"; const string WPN_SWLS_DRK = "mst_swls_drk_3"; const string WPN_SWLS_IRN = "nw_wswls001"; const string WPN_SWLS_MTH = "mst_swls_mth_3"; const string WPN_SWLS_SLV = "mst_swls_slv_3"; const string WPN_SWRP_ADA = "mst_swrp_ada_3"; const string WPN_SWRP_CLD = "mst_swrp_cld_3"; const string WPN_SWRP_DRK = "mst_swrp_drk_3"; const string WPN_SWRP_IRN = "nw_wswrp001"; const string WPN_SWRP_MTH = "mst_swrp_mth_3"; const string WPN_SWRP_SLV = "mst_swrp_slv_3"; const string WPN_SWSC_ADA = "mst_swsc_ada_3"; const string WPN_SWSC_CLD = "mst_swsc_cld_3"; const string WPN_SWSC_DRK = "mst_swsc_drk_3"; const string WPN_SWSC_IRN = "nw_wswsc001"; const string WPN_SWSC_MTH = "mst_swsc_mth_3"; const string WPN_SWSC_SLV = "mst_swsc_slv_3"; const string WPN_SWSS_ADA = "mst_swss_ada_3"; const string WPN_SWSS_CLD = "mst_swss_cld_3"; const string WPN_SWSS_DRK = "mst_swss_drk_3"; const string WPN_SWSS_IRN = "nw_wswss001"; const string WPN_SWSS_MTH = "mst_swss_mth_3"; const string WPN_SWSS_SLV = "mst_swss_slv_3"; // Warmaces const string WPN_WARMACE_ADA = "mst_bldm_ada_3"; const string WPN_WARMACE_CLD = "mst_bldm_cld_3"; const string WPN_WARMACE_DRK = "mst_bldm_drk_3"; const string WPN_WARMACE_IRN = "nw_wdbma001"; const string WPN_WARMACE_MTH = "mst_bldm_mth_3"; const string WPN_WARMACE_SLV = "mst_bldm_slv_3"; // Flails const string WPN_FLAIL_ADA = "mst_blfl_ada_3"; const string WPN_FLAIL_CLD = "mst_blfl_cld_3"; const string WPN_FLAIL_DRK = "mst_blfl_drk_3"; const string WPN_FLAIL_IRN = "nw_wblfl001"; const string WPN_FLAIL_MTH = "mst_blfl_mth_3"; const string WPN_FLAIL_SLV = "mst_blfl_slv_3"; // Constants for all Crafted Armor const string ARM_HVBM_ADA = "mwa_hvbm_ada_3"; const string ARM_HVBM_DRK = "mwa_hvbm_drk_3"; const string ARM_HVBM_IRN = "nw_aarcl011"; const string ARM_HVBM_MTH = "mwa_hvbm_mth_3"; const string ARM_HVFP_ADA = "mwa_hvfp_ada_4"; const string ARM_HVFP_DRK = "mwa_hvfp_drk_3"; const string ARM_HVFP_IRN = "nw_aarcl007"; const string ARM_HVFP_MTH = "mwa_hvfp_mth_4"; const string ARM_HVFP_SLH = "mwa_hvfp_slh_3"; const string ARM_HVFP_WYH = "mwa_hvfp_wyh_3"; const string ARM_HVHP_ADA = "mwa_hvhp_ada_4"; const string ARM_HVHP_DRK = "mwa_hvhp_drk_3"; const string ARM_HVHP_IRN = "nw_aarcl006"; const string ARM_HVHP_MTH = "mwa_hvhp_mth_4"; const string ARM_HVHP_RDH = "mwa_hvhp_rdh_3"; const string ARM_HVHP_SLH = "mwa_hvhp_slh_3"; const string ARM_HVHP_UHH = "mwa_hvhp_uhh_3"; const string ARM_HVHP_WYH = "mwa_hvhp_wyh_3"; const string ARM_LTCS_ADA = "mwa_ltcs_ada_4"; const string ARM_LTCS_DRK = "mwa_ltcs_drk_3"; const string ARM_LTCS_IRN = "nw_aarcl012"; const string ARM_LTCS_MTH = "mwa_ltcs_mth_4"; const string ARM_LTCS_SLH = "mwa_ltcs_slh_3"; const string ARM_LTLT_HID = "nw_aarcl001"; const string ARM_LTLT_SLH = "mwa_ltlt_slh_3"; const string ARM_LTPD_HID = "nw_aarcl009"; const string ARM_LTSL_HID = "nw_aarcl002"; const string ARM_LTSL_SLH = "mwa_ltsl_slh_3"; const string ARM_MDBP_ADA = "mwa_mdbp_ada_4"; const string ARM_MDBP_DRK = "mwa_mdbp_drk_3"; //const string ARM_MDBP_DSK = "mwa_mdbp_dsk_3"; // no duskwood breastplate const string ARM_MDBP_IRN = "nw_aarcl010"; const string ARM_MDBP_MTH = "mwa_mdbp_mth_4"; const string ARM_MDBP_RDH = "mwa_mdbp_rdh_3"; const string ARM_MDBP_SLH = "mwa_mdbp_slh_3"; const string ARM_MDBP_UHH = "mwa_mdbp_uhh_3"; const string ARM_MDBP_WYH = "mwa_mdbp_wyh_3"; const string ARM_MDCM_ADA = "mwa_mdcm_ada_4"; const string ARM_MDCM_DRK = "mwa_mdcm_drk_3"; const string ARM_MDCM_IRN = "nw_aarcl004"; const string ARM_MDCM_MTH = "mwa_mdcm_mth_4"; const string ARM_MDCM_SLH = "mwa_mdcm_slh_3"; const string ARM_MDHD_HID = "nw_aarcl008"; const string ARM_MDHD_SLH = "mwa_mdhd_slh_3"; const string ARM_MDSM_ADA = "mwa_mdsm_ada_4"; const string ARM_MDSM_DRK = "mwa_mdsm_drk_3"; const string ARM_MDSM_IRN = "nw_aarcl003"; const string ARM_MDSM_MTH = "mwa_mdsm_mth_4"; const string ARM_MDSM_RDH = "mwa_mdsm_rdh_3"; const string ARM_MDSM_SLH = "mwa_mdsm_slh_3"; const string ARM_MDSM_WYH = "mwa_mdsm_wyh_3"; const string ARM_SHHV_ADA = "mwa_shhv_ada_4"; const string ARM_SHHV_DRK = "mwa_shhv_drk_3"; const string ARM_SHHV_DSK = "mwa_shhv_dsk_3"; const string ARM_SHHV_IRN = "nw_ashlw001"; const string ARM_SHHV_MTH = "mwa_shhv_mth_4"; const string ARM_SHHV_UHH = "mwa_shhv_uhh_3"; const string ARM_SHHV_ZAL = "mwa_shhv_zal_3"; const string ARM_SHLT_ADA = "mwa_shlt_ada_4"; const string ARM_SHLT_DRK = "mwa_shlt_drk_3"; const string ARM_SHLT_DSK = "mwa_shlt_dsk_3"; const string ARM_SHLT_IRN = "nw_ashsw001"; const string ARM_SHLT_MTH = "mwa_shlt_mth_4"; const string ARM_SHLT_UHH = "mwa_shlt_uhh_3"; const string ARM_SHLT_ZAL = "mwa_shlt_zal_3"; const string ARM_SHTW_ADA = "mwa_shtw_ada_4"; const string ARM_SHTW_DRK = "mwa_shtw_drk_3"; const string ARM_SHTW_DSK = "mwa_shtw_dsk_3"; const string ARM_SHTW_IRN = "nw_ashto001"; const string ARM_SHTW_MTH = "mwa_shtw_mth_4"; const string ARM_SHTW_UHH = "mwa_shtw_uhh_3"; const string ARM_SHTW_ZAL = "mwa_shtw_zal_3"; // Tags of all Alchemy Ingredients const string DISTILLED_ALCOHOL = "n2_alc_disalcohol"; const string POWDERED_SILVER = "n2_alc_powsilver"; const string QUICKSILVER = "n2_alc_quicksilver"; const string DIAMOND_DUST = "n2_alc_dmnddust"; const string VENOM_GLAND = "n2_alc_venomgland"; const string GARLIC = "NW_IT_MSMLMISC24"; const string FAIRY_DUST = "NW_IT_MSMLMISC19"; const string BELLADONNA = "NW_IT_MSMLMISC23"; const string AMETHYST = "NW_IT_GEM003"; const string BEE_GLAND = "n2_alc_beegland"; const string CENTIPEDE_GLAND = "n2_alc_centgland"; const string SCORPION_GLAND = "n2_alc_scorpgland"; // Tags of all Alchemy Items const string ACID_FLASK_1 = "X1_WMGRENADE001"; const string ACID_FLASK_2 = "n2_it_acid_2"; const string ACID_FLASK_3 = "n2_it_acid_3"; const string ACID_FLASK_4 = "n2_it_acid_4"; const string ALCHEMIST_FIRE_1 = "X1_WMGRENADE002"; const string ALCHEMIST_FIRE_2 = "n2_it_alch_2"; const string ALCHEMIST_FIRE_3 = "n2_it_alch_3"; const string ALCHEMIST_FIRE_4 = "n2_it_alch_4"; const string CHOKING_POWDER_1 = "X1_WMGRENADE004"; const string CHOKING_POWDER_2 = "n2_it_chok_2"; const string CHOKING_POWDER_3 = "n2_it_chok_3"; const string CHOKING_POWDER_4 = "n2_it_chok_4"; const string HOLY_WATER_1 = "X1_WMGRENADE005"; const string HOLY_WATER_2 = "n2_it_holy_2"; const string HOLY_WATER_3 = "n2_it_holy_3"; const string HOLY_WATER_4 = "n2_it_holy_4"; const string TANGLEFOOT_BAG_1 = "X1_WMGRENADE006"; const string TANGLEFOOT_BAG_2 = "n2_it_tang_2"; const string TANGLEFOOT_BAG_3 = "n2_it_tang_3"; const string TANGLEFOOT_BAG_4 = "n2_it_tang_4"; const string THUNDERSTONE_1 = "X1_WMGRENADE007"; const string THUNDERSTONE_2 = "n2_it_thun_2"; const string THUNDERSTONE_3 = "n2_it_thun_3"; const string THUNDERSTONE_4 = "n2_it_thun_4"; const string BEE_POISON_1 = "x2_it_poison015"; const string BEE_POISON_2 = "x2_it_poison021"; const string BEE_POISON_3 = "x2_it_poison027"; const string BEE_POISON_4 = "x2_it_poison039"; const string CENTIPEDE_POISON_1 = "x2_it_poison014"; const string CENTIPEDE_POISON_2 = "x2_it_poison020"; const string CENTIPEDE_POISON_3 = "x2_it_poison026"; const string CENTIPEDE_POISON_4 = "x2_it_poison038"; const string SCORPION_POISON_1 = "x2_it_poison013"; const string SCORPION_POISON_2 = "x2_it_poison019"; const string SCORPION_POISON_3 = "x2_it_poison025"; const string SCORPION_POISON_4 = "x2_it_poison037"; // Distillation items; const string BLADELING_SPIKE = "N2_CRFT_DIST001"; const string BAT_TOOTH = "N2_CRFT_DIST002"; const string BEAR_CLAW = "N2_CRFT_DIST003"; const string DIRE_BEAR_CLAW = "N2_CRFT_DIST004"; const string BEETLE_GLAND = "N2_CRFT_DIST005"; const string FIRE_BEETLE_BELLY = "N2_CRFT_DIST006"; const string STAG_BEETLE_HORN = "N2_CRFT_DIST007"; const string DIRE_BOAR_TUSK = "N2_CRFT_DIST008"; const string BUGBEAR_TUSK = "N2_CRFT_DIST009"; const string DEMON_BLOOD = "N2_CRFT_DIST010"; const string DEVIL_BLOOD = "N2_CRFT_DIST011"; const string DRAGON_BLOOD = "N2_CRFT_DIST012"; const string GARGOYLE_HORN = "N2_CRFT_DIST014"; const string GHOUL_CLAWS = "N2_CRFT_DIST015"; const string GHAST_CLAWS = "N2_CRFT_DIST016"; const string GHOST_RESIDUE = "N2_CRFT_DIST017"; const string FIRE_GIANT_HEAD = "N2_CRFT_DIST018"; const string FROST_GIANT_HEAD = "N2_CRFT_DIST019"; const string IRON_GOLEM_FRAGMENTS = "N2_CRFT_DIST020"; const string HELLHOUND_TOOTH = "N2_CRFT_DIST021"; const string IMP_TAIL = "N2_CRFT_DIST022"; const string LICH_DUST = "N2_CRFT_DIST023"; const string FIRE_MEPHIT_HIDE = "N2_CRFT_DIST024"; const string ICE_MEPHIT_HIDE = "N2_CRFT_DIST025"; const string OGRE_MAGE_SKULL = "N2_CRFT_DIST026"; const string SHADOW_RESIDUE = "N2_CRFT_DIST027"; const string SKELETON_KNUCKLE = "N2_CRFT_DIST029"; // this is actually a skeleton rib. const string SPIDER_VENOM_GLAND = "N2_CRFT_DIST030"; const string PHASE_SPIDER_MANDIBLE = "N2_CRFT_DIST031"; const string SWORD_SPIDER_LEG = "N2_CRFT_DIST032"; const string TROLL_BLOOD = "N2_CRFT_DIST033"; const string UMBER_HULK_MANDIBLE = "N2_CRFT_DIST034"; const string VAMPIRE_TOOTH = "N2_CRFT_DIST035"; const string DIRE_WOLF_TOOTH = "N2_CRFT_DIST036"; const string WINTER_WOLF_PELT = "N2_CRFT_DIST037"; const string WRAITH_RESIDUE = "N2_CRFT_DIST038"; const string WYVERN_SCALE = "N2_CRFT_DIST039"; const string CRYSTAL_HEART = "N2_CRFT_DIST040"; // ================================================================================= // Functions // ================================================================================= // Set up the 6 recipes for typical metal weapons. void SetUpStandardMetalItem(string sMold, int iNumIngots, int iBaseSkill, string sAdamantine, string sColdIron, string sDarksteel,string sIron, string sMithral, string sSilver) { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Item sReagentList = MakeRepeatedItemList(INGOT_ADAMANTINE, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill+15, sReagentList, sAdamantine); // Cold Iron Item sReagentList = MakeRepeatedItemList(INGOT_COLD_IRON, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill+5, sReagentList, sColdIron); // Darksteel Item sReagentList = MakeRepeatedItemList(INGOT_DARKSTEEL, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill+10, sReagentList, sDarksteel); // Iron Item sReagentList = MakeRepeatedItemList(INGOT_IRON, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill, sReagentList, sIron); // Mithral Item sReagentList = MakeRepeatedItemList(INGOT_MITHRAL, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill+10, sReagentList, sMithral); // Silver Item sReagentList = MakeRepeatedItemList(INGOT_SILVER, iNumIngots); CreateMundaneRecipe(sMold, SKILL_CRAFT_WEAPON, iBaseSkill+5, sReagentList, sSilver); } // ================================================================================= // Magical recipes // ================================================================================= void SetUpMagicalRecipes1() { // Function Prototype: // void CreateMagicalRecipe(int iSpellId, string sEffect, string sTagSuffixList, string sReagentList); string sReagentList; string sRecipeEffect; //--------------------------- // ARMOR //--------------------------- // Acid Resistance I - gives Acid/10 sReagentList = MakeList(EARTH1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ACID, IP_CONST_DAMAGERESIST_10); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Acid Resistance II - gives Acid/20 sReagentList = MakeList(EARTH2, ROGUE_STONE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ACID, IP_CONST_DAMAGERESIST_20); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Acid Resistance III - gives Acid/30 sReagentList = MakeList(EARTH3, KINGS_TEAR); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ACID, IP_CONST_DAMAGERESIST_30); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 11); // Arrow Deflection - gives the Deflect Arrows feat sReagentList = MakeList(AIR2, POWER1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_BONUS_FEAT, IP_CONST_FEAT_DEFLECT_ARROWS); CreateMagicalRecipe(SPELL_MAGE_ARMOR, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 5); // Cold Resistance I - gives Cold/10 sReagentList = MakeList(WATER1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_10); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Cold Resistance II - gives Cold/20 sReagentList = MakeList(WATER2, ROGUE_STONE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_20); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Cold Resistance III - gives Cold/30 sReagentList = MakeList(WATER3, KINGS_TEAR); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_30); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 11); // Electricty Resistance I - gives Elec./10 sReagentList = MakeList(AIR1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGERESIST_10); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Electricty Resistance II - gives Elec./20 sReagentList = MakeList(AIR2, ROGUE_STONE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGERESIST_20); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Electricty Resistance III - gives Elec./30 sReagentList = MakeList(AIR3, KINGS_TEAR); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGERESIST_30); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 11); // Fire Resistance I - gives Fire/10 sReagentList = MakeList(FIRE1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGERESIST_10); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Fire Resistance II - gives Fire/20 sReagentList = MakeList(FIRE2, ROGUE_STONE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGERESIST_20); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Fire Resistance III - gives Fire/30 sReagentList = MakeList(FIRE3, KINGS_TEAR); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGERESIST_30); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 11); // Fortified Armor - gives immunity to sneak attack/critical hits sReagentList = MakeList(EARTH4, POWER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS, IP_CONST_IMMUNITYMISC_CRITICAL_HITS, IP_CONST_IMMUNITYMISC_BACKSTAB); CreateMagicalRecipe(SPELL_BANISHMENT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 13); // Invulnerable - gives Magic/10 sReagentList = MakeList(POWER4, BLUE_DIAMOND); //sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_REDUCTION, IP_CONST_DAMAGESOAK_10_HP, IP_CONST_DAMAGEREDUCTION_1, 0, DR_TYPE_MAGICBONUS); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_REDUCTION, 10, DAMAGE_TYPE_MAGICAL, 0, DR_TYPE_DMGTYPE); CreateMagicalRecipe(SPELL_STONESKIN, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 18); } void SetUpMagicalRecipes2() { // Function Prototype: // void CreateMagicalRecipe(int iSpellId, string sEffect, string sTagSuffixList, string sReagentList); string sReagentList; string sRecipeEffect; //--------------------------- // ARMOR -2 //--------------------------- // Shadowy I - gives a +5 bonus to Hide checks sReagentList = MakeList(WATER1, FIRE_OPAL); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_HIDE, 5); CreateMagicalRecipe(SPELL_INVISIBILITY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 5); // Shadowy II - gives a +10 bonus to Hide checks sReagentList = MakeList(WATER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_HIDE, 10); CreateMagicalRecipe(SPELL_INVISIBILITY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 10); // Shadowy III - gives a +15 bonus to Hide checks sReagentList = MakeList(WATER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_HIDE, 15); CreateMagicalRecipe(SPELL_INVISIBILITY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); // Silent I - gives a +5 bonus to Move Silently checks sReagentList = MakeList(WATER1, FIRE_OPAL); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_MOVE_SILENTLY, 5); CreateMagicalRecipe(SPELL_SILENCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 5); // Silent II - gives a +10 bonus to Move Silently checks sReagentList = MakeList(WATER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_MOVE_SILENTLY, 10); CreateMagicalRecipe(SPELL_SILENCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 10); // Silent III - gives a +15 bonus to Move Silently checks sReagentList = MakeList(WATER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SKILL_BONUS, SKILL_MOVE_SILENTLY, 15); CreateMagicalRecipe(SPELL_SILENCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); // Sonic Resistance I - gives Sonic/10 sReagentList = MakeList(POWER1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_SONIC, IP_CONST_DAMAGERESIST_10); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Sonic Resistance II - gives Sonic/20 sReagentList = MakeList(POWER2, ROGUE_STONE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_SONIC, IP_CONST_DAMAGERESIST_20); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Sonic Resistance III - gives Sonic/30 sReagentList = MakeList(POWER3, KINGS_TEAR); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_RESISTANCE, IP_CONST_DAMAGETYPE_SONIC, IP_CONST_DAMAGERESIST_30); CreateMagicalRecipe(SPELL_RESIST_ENERGY, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 11); // Spell Resistance I - gives SR14 sReagentList = MakeList(FIRE3, POWER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SPELL_RESISTANCE, IP_CONST_SPELLRESISTANCEBONUS_14); CreateMagicalRecipe(SPELL_SPELL_RESISTANCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); // Spell Resistance II - gives SR18 sReagentList = MakeList(FIRE4, POWER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SPELL_RESISTANCE, IP_CONST_SPELLRESISTANCEBONUS_18); CreateMagicalRecipe(SPELL_SPELL_RESISTANCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); // Spell Resistance III - gives SR22 sReagentList = MakeList(FIRE4, POWER4, BELJURIL); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SPELL_RESISTANCE, IP_CONST_SPELLRESISTANCEBONUS_22); CreateMagicalRecipe(SPELL_SPELL_RESISTANCE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); // Speed - Adds the Haste effect sReagentList = MakeList(AIR2, POWER2, BLUE_DIAMOND); //sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_HASTE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_CAST_SPELL, SPELL_HASTE, IP_CONST_CASTSPELL_NUMUSES_3_USES_PER_DAY); CreateMagicalRecipe(SPELL_HASTE, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 7); // Base +1 AC enchantment sReagentList = MakeList(EARTH1, OBSIDIAN); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 1); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 3); // Base +2 AC enchantment sReagentList = MakeList(EARTH1, DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 2); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 6); // Base +3 AC enchantment sReagentList = MakeList(EARTH2, POWER1, EMERALD); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 3); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 9); // Base +4 AC enchantment sReagentList = MakeList(EARTH3, POWER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 4); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 12); // Base +5 AC enchantment sReagentList = MakeList(EARTH3, POWER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 5); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_ARMOR_SHIELD, sReagentList, 15); } void SetUpMagicalRecipes3() { // Function Prototype: // void CreateMagicalRecipe(int iSpellId, string sEffect, string sTagSuffixList, string sReagentList); string sReagentList; string sRecipeEffect; //--------------------------- // WEAPONS //--------------------------- // Anarchic - Adds +2d6 damage against lawful creatures // FAB: Will need a check to see if the caster is Chaotic alignment sReagentList = MakeList(POWER1, AIR1, CANARY_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP, IP_CONST_ALIGNMENTGROUP_LAWFUL, IP_CONST_DAMAGETYPE_MAGICAL, IP_CONST_DAMAGEBONUS_2d6); CreateMagicalRecipe(SPELL_INFLICT_CRITICAL_WOUNDS, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Axiomatic - Adds +2d6 damage against chaotic creatures // FAB: Will need a check to see if the caster is Lawful alignment sReagentList = MakeList(POWER1, EARTH1, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP, IP_CONST_ALIGNMENTGROUP_CHAOTIC, IP_CONST_DAMAGETYPE_MAGICAL, IP_CONST_DAMAGEBONUS_2d6); CreateMagicalRecipe(SPELL_INFLICT_CRITICAL_WOUNDS, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Defending I - Adds +1 to AC sReagentList = MakeList(EARTH2, DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 1); CreateMagicalRecipe(SPELL_MAGE_ARMOR, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_SHIELD_OF_FAITH, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 8); // Defending II - Adds +2 to AC sReagentList = MakeList(EARTH3, EMERALD); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 2); CreateMagicalRecipe(SPELL_MAGE_ARMOR, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_SHIELD_OF_FAITH, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Defending III - Adds +3 to AC sReagentList = MakeList(EARTH4, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_AC_BONUS, 3); CreateMagicalRecipe(SPELL_MAGE_ARMOR, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_SHIELD_OF_FAITH, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 12); // Disruption - If an undead fails a DC14 Will save they are destroyed sReagentList = MakeList(POWER3, WATER3, JACINTH); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ON_HIT_PROPERTIES, IP_CONST_ONHIT_SLAYRACE, IP_CONST_ONHIT_SAVEDC_14, RACIAL_TYPE_UNDEAD); CreateMagicalRecipe(SPELL_UNDEATH_TO_DEATH, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 14); // Flaming - Adds 1d6 fire damage sReagentList = MakeList(FIRE2, RUBY); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGEBONUS_1d6); CreateMagicalRecipe(SPELL_FIREBALL, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_FLAME_STRIKE, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Flaming Burst - Adds 1d10 fire damage to Criticals sReagentList = MakeList(FIRE3, POWER1, FIRE_OPAL); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_MASSIVE_CRITICALS, IP_CONST_DAMAGEBONUS_1d10); CreateMagicalRecipe(SPELL_FIREBALL, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_FLAME_STRIKE, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 12); // Frost - Adds 1d6 cold damage sReagentList = MakeList(WATER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d6); CreateMagicalRecipe(SPELL_ICE_STORM, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Holy - Adds +2d6 damage against evil creatures // FAB: Will need a check to see if the caster is Good alignment sReagentList = MakeList(POWER1, WATER1, DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP, IP_CONST_ALIGNMENTGROUP_EVIL, IP_CONST_DAMAGETYPE_POSITIVE, IP_CONST_DAMAGEBONUS_2d6); CreateMagicalRecipe(SPELL_CURE_CRITICAL_WOUNDS, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Keen - Doubles Threat Range sReagentList = MakeList(EARTH2, RUBY); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_KEEN); //CreateMagicalRecipe(SPELL_KEEN_EDGE, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); CreateMagicalRecipe(SPELL_LIGHTNING_BOLT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Shock - Adds 1d6 electricity damage sReagentList = MakeList(AIR2, CANARY_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d6); CreateMagicalRecipe(SPELL_LIGHTNING_BOLT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); CreateMagicalRecipe(SPELL_CALL_LIGHTNING, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Speed - Adds the Haste effect sReagentList = MakeList(AIR2, POWER2, BLUE_DIAMOND); //sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_HASTE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_CAST_SPELL, SPELL_HASTE, IP_CONST_CASTSPELL_NUMUSES_3_USES_PER_DAY); CreateMagicalRecipe(SPELL_HASTE, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Unholy - Adds +2d6 damage against good creatures // FAB: Will need a check to see if the caster is Evil alignment sReagentList = MakeList(POWER1, FIRE1, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP, IP_CONST_ALIGNMENTGROUP_GOOD, IP_CONST_DAMAGETYPE_NEGATIVE, IP_CONST_DAMAGEBONUS_2d6); CreateMagicalRecipe(SPELL_INFLICT_CRITICAL_WOUNDS, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Poison - Adds 1d6 poison damage (possibly rename to power? get rid of?) sReagentList = MakeList(EARTH2, EMERALD); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_POISON, 4); CreateMagicalRecipe(SPELL_POISON, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList); // Life Stealing I - Adds Vampiric Regeneration 1 to the weapon sReagentList = MakeList(POWER2, FIRE2, RUBY); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_REGENERATION_VAMPIRIC, 1); CreateMagicalRecipe(SPELL_ENERVATION, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Life Stealing II - Adds Vampiric Regeneration 3 to the weapon sReagentList = MakeList(POWER3, FIRE3, CANARY_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_REGENERATION_VAMPIRIC, 3); CreateMagicalRecipe(SPELL_ENERVATION, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 11); // Life Stealing III - Adds Vampiric Regeneration 5 to the weapon sReagentList = MakeList(POWER4, FIRE4, BELJURIL); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_REGENERATION_VAMPIRIC, 5); CreateMagicalRecipe(SPELL_ENERVATION, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 15); // Luck - Adds +1 to all saves sReagentList = MakeList(POWER1, EARTH1, OBSIDIAN); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_SAVING_THROW_BONUS, 1); CreateMagicalRecipe(SPELL_RESISTANCE, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 5); } void SetUpMagicalRecipes4() { // Function Prototype: // void CreateMagicalRecipe(int iSpellId, string sEffect, string sTagSuffixList, string sReagentList); string sReagentList; string sRecipeEffect; //--------------------------- // WEAPONS //--------------------------- // Acid - Adds 1d6 acid damage sReagentList = MakeList(EARTH2, EMERALD); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_ACID, IP_CONST_DAMAGEBONUS_1d6); CreateMagicalRecipe(SPELL_MELFS_ACID_ARROW, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 10); // Hunting - Adds +2d6 damage against beasts sReagentList = MakeList(POWER1, WATER1, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP, IP_CONST_RACIALTYPE_BEAST, IP_CONST_DAMAGETYPE_MAGICAL, IP_CONST_DAMAGEBONUS_2d6); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 7); // Base Enchantment +1 sReagentList = MakeList(AIR1, OBSIDIAN); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ENHANCEMENT_BONUS, 1); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 3); // Base Enchantment +2 sReagentList = MakeList(AIR1, DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ENHANCEMENT_BONUS, 2); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 6); // Base Enchantment +3 sReagentList = MakeList(AIR2, POWER1, EMERALD); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ENHANCEMENT_BONUS, 3); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 9); // Base Enchantment +4 sReagentList = MakeList(AIR3, POWER2, STAR_SAPPHIRE); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ENHANCEMENT_BONUS, 4); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 12); // Base Enchantment +5 sReagentList = MakeList(AIR3, POWER3, BLUE_DIAMOND); sRecipeEffect = MakeEncodedEffect(ITEM_PROPERTY_ENHANCEMENT_BONUS, 5); CreateMagicalRecipe(SPELL_LIGHT, sRecipeEffect, ITEM_CATEGORY_WEAPON, sReagentList, 15); } // ================================================================================= // Wondrous recipes // ================================================================================= void SetUpWondrousRecipes1() { // Function Prototype: // void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef); string sReagentList; // Boots of Striding +2 sReagentList = MakeList(EARTH1, DIAMOND, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BEARS_ENDURANCE, sReagentList, BOOTS_STRIDING_2, 8); // Boots of Striding +4 sReagentList = MakeList(EARTH2, JACINTH, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BEARS_ENDURANCE, sReagentList, BOOTS_STRIDING_4, 8); // Boots of Striding +6 sReagentList = MakeList(EARTH3, ROGUE_STONE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BEARS_ENDURANCE, sReagentList, BOOTS_STRIDING_6, 8); // Boots of Striding +8 sReagentList = MakeList(EARTH4, BELJURIL, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BEARS_ENDURANCE, sReagentList, BOOTS_STRIDING_8, 8); // Amulet of Natural Armor +1 sReagentList = MakeList(EARTH1, SAPPHIRE, INGOT_IRON); CreateWondrousRecipe(SPELL_BARKSKIN, sReagentList, AMULET_NATURAL_ARMOR_1, 5); // Amulet of Natural Armor +2 sReagentList = MakeList(EARTH2, EMERALD, INGOT_IRON); CreateWondrousRecipe(SPELL_BARKSKIN, sReagentList, AMULET_NATURAL_ARMOR_2, 6); // Amulet of Natural Armor +3 sReagentList = MakeList(EARTH3, POWER1, JACINTH, INGOT_IRON); CreateWondrousRecipe(SPELL_BARKSKIN, sReagentList, AMULET_NATURAL_ARMOR_3, 9); // Amulet of Natural Armor +4 sReagentList = MakeList(EARTH3, POWER2, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_BARKSKIN, sReagentList, AMULET_NATURAL_ARMOR_4, 12); // Amulet of Natural Armor +5 sReagentList = MakeList(EARTH4, POWER2, BELJURIL, INGOT_IRON); CreateWondrousRecipe(SPELL_BARKSKIN, sReagentList, AMULET_NATURAL_ARMOR_5, 15); // Belt of Frost Giant Strength +4 sReagentList = MakeList(FIRE2, BLUE_DIAMOND, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BULLS_STRENGTH, sReagentList, BELT_FROST_GIANT_STRENGTH, 8); // Belt of Stone Giant Strength +6 sReagentList = MakeList(FIRE3, BELJURIL, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BULLS_STRENGTH, sReagentList, BELT_STONE_GIANT_STRENGTH, 8); // Belt of Cloud Giant Strength +8 sReagentList = MakeList(FIRE4, KINGS_TEAR, HIDE_LEATHER); CreateWondrousRecipe(SPELL_BULLS_STRENGTH, sReagentList, BELT_CLOUD_GIANT_STRENGTH, 8); // Boots of Elvenkind // FAB: Check to see if the crafter is an elf sReagentList = MakeList(WATER1, FIRE_OPAL, HIDE_LEATHER); CreateWondrousRecipe(SPELL_SILENCE, sReagentList, BOOTS_ELVENKIND, 5); // Boots of Speed sReagentList = MakeList(AIR2, POWER2, STAR_SAPPHIRE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_HASTE, sReagentList, BOOTS_SPEED, 7); // Bracers of Armor +1 sReagentList = MakeList(EARTH1, OBSIDIAN, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_1, 7); // Bracers of Armor +2 sReagentList = MakeList(EARTH1, DIAMOND, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_2, 7); // Bracers of Armor +3 sReagentList = MakeList(EARTH2, CANARY_DIAMOND, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_3, 7); // Bracers of Armor +4 sReagentList = MakeList(EARTH2, JACINTH, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_4, 8); // Bracers of Armor +5 sReagentList = MakeList(EARTH3, BLUE_DIAMOND, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_5, 10); // Bracers of Armor +6 sReagentList = MakeList(EARTH3, ROGUE_STONE, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_6, 12); // Bracers of Armor +7 sReagentList = MakeList(EARTH4, BELJURIL, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_7, 14); // Bracers of Armor +8 sReagentList = MakeList(EARTH4, KINGS_TEAR, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BRACERS_ARMOR_8, 16); } void SetUpWondrousRecipes2() { // Function Prototype: // void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef); string sReagentList; // Brooch of Shielding sReagentList = MakeList(POWER1, SAPPHIRE, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, BROOCH_SHIELDING, 1); // Nymph Cloak +2 sReagentList = MakeList(WATER1, DIAMOND, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_EAGLE_SPLEDOR, sReagentList, NYMPH_CLOAK_2, 8); // Nymph Cloak +4 sReagentList = MakeList(WATER2, STAR_SAPPHIRE, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_EAGLE_SPLEDOR, sReagentList, NYMPH_CLOAK_4, 8); // Nymph Cloak +6 sReagentList = MakeList(WATER3, ROGUE_STONE, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_EAGLE_SPLEDOR, sReagentList, NYMPH_CLOAK_6, 8); // Nymph Cloak +8 sReagentList = MakeList(WATER4, BELJURIL, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_EAGLE_SPLEDOR, sReagentList, NYMPH_CLOAK_8, 8); // Cloak of Displacement sReagentList = MakeList(AIR2, BLUE_DIAMOND, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_DISPLACEMENT, sReagentList, CLOAK_DISPLACEMENT, 3); // Cloak of Elvenkind // FAB: Check to see if the crafter is an elf sReagentList = MakeList(WATER1, FIRE_OPAL, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_INVISIBILITY, sReagentList, CLOAK_ELVENKIND, 3); // Cloak of Resistance +1 sReagentList = MakeList(EARTH1, OBSIDIAN, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_RESISTANCE, sReagentList, CLOAK_RESISTANCE_1, 5); // Cloak of Resistance +2 sReagentList = MakeList(EARTH1, DIAMOND, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_RESISTANCE, sReagentList, CLOAK_RESISTANCE_2, 6); // Cloak of Resistance +3 sReagentList = MakeList(EARTH2, CANARY_DIAMOND, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_RESISTANCE, sReagentList, CLOAK_RESISTANCE_3, 9); // Cloak of Resistance +4 sReagentList = MakeList(EARTH3, JACINTH, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_RESISTANCE, sReagentList, CLOAK_RESISTANCE_4, 12); // Cloak of Resistance +5 sReagentList = MakeList(EARTH4, BLUE_DIAMOND, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_RESISTANCE, sReagentList, CLOAK_RESISTANCE_5, 15); // Eyes of the Eagle //sReagentList = MakeList(AIR1, FIRE_OPAL, INGOT_IRON); //CreateWondrousRecipe(SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE, sReagentList, EYES_EAGLE, 3); // Gauntlets of Ogre Power sReagentList = MakeList(FIRE1, RUBY, INGOT_IRON, INGOT_IRON); CreateWondrousRecipe(SPELL_BULLS_STRENGTH, sReagentList, GAUNTLETS_OGRE_POWER, 6); // Gem of Seeing sReagentList = MakeList(AIR2, KINGS_TEAR); CreateWondrousRecipe(SPELL_TRUE_SEEING, sReagentList, GEM_SEEING, 10); // Belt of Agility +2 sReagentList = MakeList(AIR1, DIAMOND, HIDE_LEATHER); CreateWondrousRecipe(SPELL_CATS_GRACE, sReagentList, BELT_AGILITY_2, 8); // Belt of Agility +4 sReagentList = MakeList(AIR2, STAR_SAPPHIRE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_CATS_GRACE, sReagentList, BELT_AGILITY_4, 8); // Belt of Agility +6 sReagentList = MakeList(AIR3, ROGUE_STONE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_CATS_GRACE, sReagentList, BELT_AGILITY_6, 8); // Belt of Agility +8 sReagentList = MakeList(AIR4, BELJURIL, HIDE_LEATHER); CreateWondrousRecipe(SPELL_CATS_GRACE, sReagentList, BELT_AGILITY_8, 8); // Goggles of Minute Seeing //sReagentList = MakeList(AIR1, OBSIDIAN, INGOT_IRON); //CreateWondrousRecipe(SPELL_TRUE_SEEING, sReagentList, GOGGLES_MINUTE_SEEING, 3); // Goggles of Night //sReagentList = MakeList(POWER1, STAR_SAPPHIRE, INGOT_IRON); //CreateWondrousRecipe(SPELL_LIGHT, sReagentList, GOGGLES_NIGHT, 3); // Headband of Intellect +2 sReagentList = MakeList(FIRE1, DIAMOND, HIDE_LEATHER); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, HEADBAND_INTELLECT_2, 9); // Headband of Intellect +4 sReagentList = MakeList(FIRE2, STAR_SAPPHIRE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, HEADBAND_INTELLECT_4, 8); // Headband of Intellect +6 sReagentList = MakeList(FIRE3, ROGUE_STONE, HIDE_LEATHER); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, HEADBAND_INTELLECT_6, 8); // Headband of Intellect +8 sReagentList = MakeList(FIRE4, BELJURIL, HIDE_LEATHER); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, HEADBAND_INTELLECT_8, 8); } void SetUpWondrousRecipes3() { // Function Prototype: // void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef); string sReagentList; // Horn of Goodness // sReagentList = MakeList(POWER2, WATER2, EMERALD, INGOT_IRON); //CreateWondrousRecipe(SPELL_MAGIC_CIRCLE_AGAINST_EVIL, sReagentList, HORN_GOODNESS, 6); // Greater Mantle of Spell Resistance sReagentList = MakeList(POWER4, FIRE4, KINGS_TEAR, HIDE_LEATHER, HIDE_LEATHER); CreateWondrousRecipe(SPELL_SPELL_RESISTANCE, sReagentList, MANTLE_GREATER_SPELL_RESISTANCE, 9); // Medallion of Thought sReagentList = MakeList(WATER2, POWER2, CANARY_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, MEDALLION_THOUGHTS, 8); // Ring of Divine Power 1 sReagentList = MakeList(FIRE1, OBSIDIAN, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, RING_DIVINE_POWER_1, 8); // Ring of Divine Power 2 sReagentList = MakeList(FIRE2, OBSIDIAN, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, RING_DIVINE_POWER_2, 8); // Ring of Divine Power 3 sReagentList = MakeList(POWER1, FIRE2, CANARY_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, RING_DIVINE_POWER_3, 8); // Ring of Divine Power 4 sReagentList = MakeList(POWER2, FIRE3, STAR_SAPPHIRE, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, RING_DIVINE_POWER_4, 9); // Ring of Divine Power 5 sReagentList = MakeList(POWER3, FIRE4, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, RING_DIVINE_POWER_5, 11); } void SetUpWondrousRecipes3a() { // Function Prototype: // void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef); string sReagentList; // Ring of Wizardry 1 sReagentList = MakeList(AIR1, OBSIDIAN, INGOT_IRON); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, RING_WIZARDRY_1, 8); // Ring of Wizardry 2 sReagentList = MakeList(AIR2, OBSIDIAN, INGOT_IRON); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, RING_WIZARDRY_2, 8); // Ring of Wizardry 3 sReagentList = MakeList(POWER1, AIR2, CANARY_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, RING_WIZARDRY_3, 8); // Ring of Wizardry 4 sReagentList = MakeList(POWER2, AIR3, STAR_SAPPHIRE, INGOT_IRON); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, RING_WIZARDRY_4, 9); // Ring of Wizardry 5 sReagentList = MakeList(POWER3, AIR4, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_FOXS_CUNNING, sReagentList, RING_WIZARDRY_5, 11); // Lesser Amulet of Health sReagentList = MakeList(POWER2, WATER2, OBSIDIAN, INGOT_IRON); CreateWondrousRecipe(SPELL_REMOVE_DISEASE, sReagentList, LESSER_AMULET_HEALTH, 5); CreateWondrousRecipe(SPELL_NEUTRALIZE_POISON, sReagentList, LESSER_AMULET_HEALTH, 5); // Amulet of Health sReagentList = MakeList(POWER3, WATER3, CANARY_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_REMOVE_DISEASE, sReagentList, AMULET_HEALTH, 5); CreateWondrousRecipe(SPELL_NEUTRALIZE_POISON, sReagentList, AMULET_HEALTH, 5); // Amulet of Health sReagentList = MakeList(POWER4, WATER4, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_REMOVE_DISEASE, sReagentList, GREATER_AMULET_HEALTH, 5); CreateWondrousRecipe(SPELL_NEUTRALIZE_POISON, sReagentList, GREATER_AMULET_HEALTH, 5); } void SetUpWondrousRecipes3b() { // Function Prototype: // void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef); string sReagentList; // Periapt of Wisdom +2 sReagentList = MakeList(WATER1, DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, PERIAPT_WISDOM_2, 8); // Periapt of Wisdom +4 sReagentList = MakeList(WATER2, STAR_SAPPHIRE, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, PERIAPT_WISDOM_4, 8); // Periapt of Wisdom +6 sReagentList = MakeList(WATER3, ROGUE_STONE, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, PERIAPT_WISDOM_6, 8); // Periapt of Wisdom +8 sReagentList = MakeList(WATER4, BELJURIL, INGOT_IRON); CreateWondrousRecipe(SPELL_OWLS_WISDOM, sReagentList, PERIAPT_WISDOM_8, 8); // Robe of the Archmage sReagentList = MakeList(WATER4, FIRE4, EARTH4, AIR4, POWER3, KINGS_TEAR, INGOT_IRON, HIDE_LEATHER); CreateWondrousRecipe(SPELL_MAGE_ARMOR, sReagentList, ROBE_ARCHMAGE, 14); CreateWondrousRecipe(SPELL_SHIELD_OF_FAITH, sReagentList, ROBE_ARCHMAGE, 14); // Scabbard of Keen Edges sReagentList = MakeList(EARTH1, JACINTH, PLANK_WOOD); CreateWondrousRecipe(SPELL_KEEN_EDGE, sReagentList, SCABBARD_KEEN_EDGES, 5); // Greater Scarab of Protection sReagentList = MakeList(POWER4, FIRE4, WATER4, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_DEATH_WARD, sReagentList, SCARAB_GREATER_PROTECTION, 18); // The charm and focus can be created using standard darkness or the warlock invocation darkness // Gold Filigree Charm // TDE: used for summoning Mephasm in Crossroad Keep sReagentList = MakeList(POWER1, FIRE3, STAR_SAPPHIRE, GOLD_NECKLACE); CreateWondrousRecipe(SPELL_DARKNESS, sReagentList, MEPHASM_CHARM); CreateWondrousRecipe(SPELL_I_DARKNESS, sReagentList, MEPHASM_CHARM); // Infernal Focus 1 // TDE: used for bargaining with Mephasm in Crossroad Keep sReagentList = MakeList(POWER3, RUBY, INGOT_DARKSTEEL); CreateWondrousRecipe(SPELL_DARKNESS, sReagentList, MEPHASM_FOCUS); CreateWondrousRecipe(SPELL_I_DARKNESS, sReagentList, MEPHASM_FOCUS); // Infernal Focus 2 // TDE: used for bargaining with Mephasm in Crossroad Keep sReagentList = MakeList(FIRE3, SAPPHIRE, INGOT_MITHRAL); CreateWondrousRecipe(SPELL_DARKNESS, sReagentList, MEPHASM_FOCUS); CreateWondrousRecipe(SPELL_I_DARKNESS, sReagentList, MEPHASM_FOCUS); // Infernal Focus 3 // TDE: used for bargaining with Mephasm in Crossroad Keep sReagentList = MakeList(POWER1, FIRE1, BLUE_DIAMOND, INGOT_IRON); CreateWondrousRecipe(SPELL_DARKNESS, sReagentList, MEPHASM_FOCUS); CreateWondrousRecipe(SPELL_I_DARKNESS, sReagentList, MEPHASM_FOCUS); } // ================================================================================= // Mundane recipes // ================================================================================= void SetUpMundaneRecipes1() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Battleaxe sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_AXBT_ADA); // Cold Iron Battleaxe sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXBT_CLD); // Darksteel Battleaxe sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXBT_DRK); // Iron Battleaxe sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_AXBT_IRN); // Mithral Battleaxe sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXBT_MTH); // Silver Battleaxe sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_AXBT, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXBT_SLV); // Adamantine Dwarven waraxe sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_AXDV_ADA); // Cold Iron Dwarven waraxe sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_AXDV_CLD); // Darksteel Dwarven waraxe sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_AXDV_DRK); // Iron Dwarven waraxe sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_AXDV_IRN); // Mithral Dwarven waraxe sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_AXDV_MTH); // Silver Dwarven waraxe sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_AXDV, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_AXDV_SLV); // Adamantine Greataxe sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_AXGR_ADA); // Cold Iron Greataxe sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXGR_CLD); // Darksteel Greataxe sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXGR_DRK); // Iron Greataxe sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_AXGR_IRN); // Mithral Greataxe sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXGR_MTH); // Silver Greataxe sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_AXGR, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXGR_SLV); } void SetUpMundaneRecipes2() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Handaxe sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_AXHN_ADA); // Cold Iron Handaxe sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXHN_CLD); // Darksteel Handaxe sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXHN_DRK); // Iron Handaxe sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_AXHN_IRN); // Mithral Handaxe sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_AXHN_MTH); // Silver Handaxe sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_AXHN, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_AXHN_SLV); // Duskwood Club sReagentList = MakeList(PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_BLCL, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BLCL_DSK); // Wooden Club sReagentList = MakeList(PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_BLCL, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_BLCL_LAN); // Zalantar Club sReagentList = MakeList(PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_BLCL, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BLCL_ZAL); } void SetUpMundaneRecipes3() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // ------------------------------------------------------------------------------------- // Adamantine Hammer, light sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_BLHL_ADA); // Cold Iron Hammer, light sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BLHL_CLD); // Darksteel Hammer, light sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BLHL_DRK); // Iron Hammer, light sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_BLHL_IRN); // Mithral Hammer, light sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BLHL_MTH); // Silver Hammer, light sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_BLHL, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BLHL_SLV); // ------------------------------------------------------------------------------------- // Adamantine Warhammer sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_BLHW_ADA); // Cold Iron Warhammer sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BLHW_CLD); // Darksteel Warhammer sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BLHW_DRK); // Iron Warhammer sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_BLHW_IRN); // Mithral Warhammer sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BLHW_MTH); // Silver Warhammer sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_BLHW, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BLHW_SLV); // ------------------------------------------------------------------------------------- // Adamantine Mace sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 17, sReagentList, WPN_BLML_ADA); // Cold Iron Mace sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BLML_CLD); // Darksteel Mace sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BLML_DRK); // Iron Mace sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_BLML_IRN); // Mithral Mace sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BLML_MTH); // Silver Mace sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_BLML, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BLML_SLV); // ------------------------------------------------------------------------------------- // Adamantine War Mace sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_WARMACE_ADA); // Cold Iron War Mace sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_WARMACE_CLD); // Darksteel War Mace sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_WARMACE_DRK); // Iron War Mace sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_WARMACE_IRN); // Mithral War Mace sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_WARMACE_MTH); // Silver War Mace sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_WARMACE, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_WARMACE_SLV); } void SetUpMundaneRecipes4() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Morningstar sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 17, sReagentList, WPN_BLMS_ADA); // Cold Iron Morningstar sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BLMS_CLD); // Darksteel Morningstar sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BLMS_DRK); // Iron Morningstar sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_BLMS_IRN); // Mithral Morningstar sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BLMS_MTH); // Silver Morningstar sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_BLMS, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BLMS_SLV); // Duskwood Longbow* sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_BWLN, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BWLN_DSK); // Wooden Longbow* sReagentList = MakeList(PLANK_WOOD, PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_BWLN, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_BWLN_LAN); // Shederran Longbow* sReagentList = MakeList(PLANK_SHEDERRAN, PLANK_SHEDERRAN); CreateMundaneRecipe(MOLD_WPN_BWLN, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BWLN_SHD); // Zalantar Longbow* sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_BWLN, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BWLN_ZAL); // Duskwood Shortbow* sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_BWSH, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_BWSH_DSK); // Wooden Shortbow* sReagentList = MakeList(PLANK_WOOD, PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_BWSH, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_BWSH_LAN); // Shederran Shortbow* sReagentList = MakeList(PLANK_SHEDERRAN, PLANK_SHEDERRAN); CreateMundaneRecipe(MOLD_WPN_BWSH, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BWSH_SHD); // Zalantar Shortbow* sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_BWSH, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_BWSH_ZAL); // Duskwood Crossbow, heavy* sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_BWXH, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BWXH_DSK); // Wooden Crossbow, heavy* sReagentList = MakeList(PLANK_WOOD, PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_BWXH, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_BWXH_LAN); // Shederran Crossbow, heavy* sReagentList = MakeList(PLANK_SHEDERRAN, PLANK_SHEDERRAN); CreateMundaneRecipe(MOLD_WPN_BWXH, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_BWXH_SHD); // Zalantar Crossbow, heavy* sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_BWXH, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BWXH_ZAL); // Duskwood Crossbow, light* sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_BWXL, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_BWXL_DSK); // Wooden Crossbow, light* sReagentList = MakeList(PLANK_WOOD, PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_BWXL, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_BWXL_LAN); // Shederran Crossbow, light* sReagentList = MakeList(PLANK_SHEDERRAN, PLANK_SHEDERRAN); CreateMundaneRecipe(MOLD_WPN_BWXL, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_BWXL_SHD); // Zalantar Crossbow, light* sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_BWXL, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_BWXL_ZAL); } void SetUpMundaneRecipes5() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Duskwood Quarterstaff sReagentList = MakeList(PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_DBQS, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_DBQS_DSK); // Wooden Quarterstaff sReagentList = MakeList(PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_DBQS, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_DBQS_LAN); // Zalantar Quarterstaff sReagentList = MakeList(PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_DBQS, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_DBQS_ZAL); // Adamantine Halberd sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_PLHB_ADA); // Cold Iron Halberd sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_PLHB_CLD); // Darksteel Halberd sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_PLHB_DRK); // Iron Halberd sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_PLHB_IRN); // Mithral Halberd sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_PLHB_MTH); // Silver Halberd sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_PLHB, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_PLHB_SLV); // Adamantine Scythe sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_PLSC_ADA); // Cold Iron Scythe sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_PLSC_CLD); // Darksteel Scythe sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_PLSC_DRK); // Iron Scythe sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_PLSC_IRN); // Mithral Scythe sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_PLSC_MTH); // Silver Scythe sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_PLSC, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_PLSC_SLV); // Duskwood Spear sReagentList = MakeList(PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_WPN_PLSS, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_PLSS_DSK); // Wooden Spear sReagentList = MakeList(PLANK_WOOD); CreateMundaneRecipe(MOLD_WPN_PLSS, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_PLSS_LAN); // Zalantar Spear sReagentList = MakeList(PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_WPN_PLSS, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_PLSS_ZAL); // Adamantine Kama sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_SPKA_ADA); // Cold Iron Kama sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SPKA_CLD); // Darksteel Kama sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SPKA_DRK); // Iron Kama sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_SPKA_IRN); // Mithral Kama sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SPKA_MTH); // Silver Kama sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SPKA, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SPKA_SLV); } void SetUpMundaneRecipes6() { // Kukri SetUpStandardMetalItem(MOLD_WPN_SPKU, 1, 8, WPN_SPKU_ADA, WPN_SPKU_CLD, WPN_SPKU_DRK, WPN_SPKU_IRN, WPN_SPKU_MTH, WPN_SPKU_SLV); // Sickle SetUpStandardMetalItem(MOLD_WPN_SPSC, 1, 2, WPN_SPSC_ADA, WPN_SPSC_CLD, WPN_SPSC_DRK, WPN_SPSC_IRN, WPN_SPSC_MTH, WPN_SPSC_SLV); // Bastard Sword SetUpStandardMetalItem(MOLD_WPN_SWBS, 2, 8, WPN_SWBS_ADA, WPN_SWBS_CLD, WPN_SWBS_DRK, WPN_SWBS_IRN, WPN_SWBS_MTH, WPN_SWBS_SLV); // Falchion SetUpStandardMetalItem(MOLD_WPN_SWFL, 2, 8, WPN_SWFL_ADA, WPN_SWFL_CLD, WPN_SWFL_DRK, WPN_SWFL_IRN, WPN_SWFL_MTH, WPN_SWFL_SLV); /* // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // ------------------------------------------------------------------------------------- // Adamantine Kukri sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_SPKU_ADA); // Cold Iron Kukri sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SPKU_CLD); // Darksteel Kukri sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SPKU_DRK); // Iron Kukri sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_SPKU_IRN); // Mithral Kukri sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SPKU_MTH); // Silver Kukri sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SPKU, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SPKU_SLV); // ------------------------------------------------------------------------------------- // Adamantine Sickle sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 17, sReagentList, WPN_SPSC_ADA); // Cold Iron Sickle sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_SPSC_CLD); // Darksteel Sickle sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_SPSC_DRK); // Iron Sickle sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_SPSC_IRN); // Mithral Sickle sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_SPSC_MTH); // Silver Sickle sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SPSC, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_SPSC_SLV); // ------------------------------------------------------------------------------------- // Adamantine Bastard sword sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_SWBS_ADA); // Cold Iron Bastard sword sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SWBS_CLD); // Darksteel Bastard sword sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWBS_DRK); // Iron Bastard sword sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_SWBS_IRN); // Mithral Bastard sword sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWBS_MTH); // Silver Bastard sword sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWBS, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SPSC_SLV); // ------------------------------------------------------------------------------------- // Adamantine Falchion sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_SWFL_ADA); // Cold Iron Falchion sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SWFL_CLD); // Darksteel Falchion sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWFL_DRK); // Iron Falchion sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_SWFL_IRN); // Mithral Falchion sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWFL_MTH); // Silver Falchion sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWFL, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWFL_SLV); */ } void SetUpMundaneRecipes7() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Dagger sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 17, sReagentList, WPN_SWDG_ADA); // Cold Iron Dagger sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_SWDG_CLD); // Darksteel Dagger sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_SWDG_DRK); // Iron Dagger sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 2, sReagentList, WPN_SWDG_IRN); // Mithral Dagger sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 12, sReagentList, WPN_SWDG_MTH); // Silver Dagger sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWDG, SKILL_CRAFT_WEAPON, 7, sReagentList, WPN_SWDG_SLV); // Adamantine Greatsword sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_SWGS_ADA); // Cold Iron Greatsword sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWGS_CLD); // Darksteel Greatsword sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWGS_DRK); // Iron Greatsword sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_SWGS_IRN); // Mithral Greatsword sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWGS_MTH); // Silver Greatsword sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWGS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWGS_SLV); // Adamantine Katana sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 23, sReagentList, WPN_SWKA_ADA); // Cold Iron Katana sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SWKA_CLD); // Darksteel Katana sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWKA_DRK); // Iron Katana sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 8, sReagentList, WPN_SWKA_IRN); // Mithral Katana sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 18, sReagentList, WPN_SWKA_MTH); // Silver Katana sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWKA, SKILL_CRAFT_WEAPON, 13, sReagentList, WPN_SWKA_SLV); // Adamantine Longsword sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_SWLS_ADA); // Cold Iron Longsword sReagentList = MakeList(INGOT_COLD_IRON, INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWLS_CLD); // Darksteel Longsword sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWLS_DRK); // Iron Longsword sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_SWLS_IRN); // Mithral Longsword sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWLS_MTH); // Silver Longsword sReagentList = MakeList(INGOT_SILVER, INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWLS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWLS_SLV); } void SetUpMundaneRecipes8() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Rapier sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_SWRP_ADA); // Cold Iron Rapier sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWRP_CLD); // Darksteel Rapier sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWRP_DRK); // Iron Rapier sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_SWRP_IRN); // Mithral Rapier sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWRP_MTH); // Silver Rapier sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWRP, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWRP_SLV); // Adamantine Scimitar sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_SWSC_ADA); // Cold Iron Scimitar sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWSC_CLD); // Darksteel Scimitar sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWSC_DRK); // Iron Scimitar sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_SWSC_IRN); // Mithral Scimitar sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWSC_MTH); // Silver Scimitar sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWSC, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWSC_SLV); // Adamantine Shortsword sReagentList = MakeList(INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 20, sReagentList, WPN_SWSS_ADA); // Cold Iron Shortsword sReagentList = MakeList(INGOT_COLD_IRON); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWSS_CLD); // Darksteel Shortsword sReagentList = MakeList(INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWSS_DRK); // Iron Shortsword sReagentList = MakeList(INGOT_IRON); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 5, sReagentList, WPN_SWSS_IRN); // Mithral Shortsword sReagentList = MakeList(INGOT_MITHRAL); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 15, sReagentList, WPN_SWSS_MTH); // Silver Shortsword sReagentList = MakeList(INGOT_SILVER); CreateMundaneRecipe(MOLD_WPN_SWSS, SKILL_CRAFT_WEAPON, 10, sReagentList, WPN_SWSS_SLV); // Adamantine Full Plate sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_HVFP, SKILL_CRAFT_ARMOR, 23, sReagentList, ARM_HVFP_ADA); // Darksteel Full Plate sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_HVFP, SKILL_CRAFT_ARMOR, 18, sReagentList, ARM_HVFP_DRK); // Iron Full Plate sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_HVFP, SKILL_CRAFT_ARMOR, 8, sReagentList, ARM_HVFP_IRN); // Mithral Full Plate sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_HVFP, SKILL_CRAFT_ARMOR, 18, sReagentList, ARM_HVFP_MTH); // Wyvern Hide Full Plate sReagentList = MakeList(HIDE_WYVERN, HIDE_WYVERN, HIDE_WYVERN); CreateMundaneRecipe(MOLD_ARM_HVFP, SKILL_CRAFT_ARMOR, 28, sReagentList, ARM_HVFP_WYH); } void SetUpMundaneRecipes9() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Half-plate sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 22, sReagentList, ARM_HVHP_ADA); // Darksteel Half-plate sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 17, sReagentList, ARM_HVHP_DRK); // Iron Half-plate sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 7, sReagentList, ARM_HVHP_IRN); // Mithral Half-plate sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 17, sReagentList, ARM_HVHP_MTH); // Red Dragon Hide Half-plate sReagentList = MakeList(HIDE_DRAGON, HIDE_DRAGON, HIDE_DRAGON); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 30, sReagentList, ARM_HVHP_RDH); // Umber Hulk Hide Half-plate sReagentList = MakeList(HIDE_UMBER_HULK, HIDE_UMBER_HULK, HIDE_UMBER_HULK); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 24, sReagentList, ARM_HVHP_UHH); // Wyvern Hide Half-plate sReagentList = MakeList(HIDE_WYVERN, HIDE_WYVERN, HIDE_WYVERN); CreateMundaneRecipe(MOLD_ARM_HVHP, SKILL_CRAFT_ARMOR, 27, sReagentList, ARM_HVHP_WYH); // Adamantine Chain Shirt sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_LTCS, SKILL_CRAFT_ARMOR, 19, sReagentList, ARM_LTCS_ADA); // Darksteel Chain Shirt sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_LTCS, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_LTCS_DRK); // Iron Chain Shirt sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_LTCS, SKILL_CRAFT_ARMOR, 4, sReagentList, ARM_LTCS_IRN); // Mithral Chain Shirt sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_LTCS, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_LTCS_MTH); } void SetUpMundaneRecipes9a() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Iron Banded Mail sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_HVBM, SKILL_CRAFT_ARMOR, 6, sReagentList, ARM_HVBM_IRN); // Adamantine Banded Mail sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_HVBM, SKILL_CRAFT_ARMOR, 21, sReagentList, ARM_HVBM_ADA); // Darksteel Banded Mail sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_HVBM, SKILL_CRAFT_ARMOR, 16, sReagentList, ARM_HVBM_DRK); // Mithral Banded Mail sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_HVBM, SKILL_CRAFT_ARMOR, 16, sReagentList, ARM_HVBM_MTH); // Leather Leather sReagentList = MakeList(HIDE_LEATHER, HIDE_LEATHER, HIDE_LEATHER); CreateMundaneRecipe(MOLD_ARM_LTLT, SKILL_CRAFT_ARMOR, 4, sReagentList, ARM_LTLT_HID); // Salamander Hide Leather sReagentList = MakeList(HIDE_SALAMANDER, HIDE_SALAMANDER, HIDE_SALAMANDER); CreateMundaneRecipe(MOLD_ARM_LTLT, SKILL_CRAFT_ARMOR, 16, sReagentList, ARM_LTLT_SLH); // Leather Studded Leather sReagentList = MakeList(HIDE_LEATHER, HIDE_LEATHER, HIDE_LEATHER); CreateMundaneRecipe(MOLD_ARM_LTSL, SKILL_CRAFT_ARMOR, 5, sReagentList, ARM_LTSL_HID); // Salamander Hide Studded Leather sReagentList = MakeList(HIDE_SALAMANDER, HIDE_SALAMANDER, HIDE_SALAMANDER); CreateMundaneRecipe(MOLD_ARM_LTSL, SKILL_CRAFT_ARMOR, 17, sReagentList, ARM_LTSL_SLH); // Adamantine Breastplate sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 20, sReagentList, ARM_MDBP_ADA); // Darksteel Breastplate sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 15, sReagentList, ARM_MDBP_DRK); // Duskwood Breastplate //sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD, PLANK_DUSKWOOD); //CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 10, sReagentList, ARM_MDBP_DSK); // Iron Breastplate sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 5, sReagentList, ARM_MDBP_IRN); // Mithral Breastplate sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 15, sReagentList, ARM_MDBP_MTH); } void SetUpMundaneRecipes10() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Red Dragon Hide Breastplate sReagentList = MakeList(HIDE_DRAGON, HIDE_DRAGON, HIDE_DRAGON); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 28, sReagentList, ARM_MDBP_RDH); // Umber Hulk Hide Breastplate sReagentList = MakeList(HIDE_UMBER_HULK, HIDE_UMBER_HULK, HIDE_UMBER_HULK); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 22, sReagentList, ARM_MDBP_UHH); // Wyvern Hide Breastplate sReagentList = MakeList(HIDE_WYVERN, HIDE_WYVERN, HIDE_WYVERN); CreateMundaneRecipe(MOLD_ARM_MDBP, SKILL_CRAFT_ARMOR, 25, sReagentList, ARM_MDBP_WYH); // Adamantine Chainmail sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_MDCM, SKILL_CRAFT_ARMOR, 20, sReagentList, ARM_MDCM_ADA); // Darksteel Chainmail sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_MDCM, SKILL_CRAFT_ARMOR, 15, sReagentList, ARM_MDCM_DRK); // Iron Chainmail sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_MDCM, SKILL_CRAFT_ARMOR, 5, sReagentList, ARM_MDCM_IRN); // Mithral Chainmail sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_MDCM, SKILL_CRAFT_ARMOR, 15, sReagentList, ARM_MDCM_MTH); // Leather Hide sReagentList = MakeList(HIDE_LEATHER, HIDE_LEATHER); CreateMundaneRecipe(MOLD_ARM_MDHD, SKILL_CRAFT_ARMOR, 5, sReagentList, ARM_MDHD_HID); //Salamander Hide sReagentList = MakeList(HIDE_SALAMANDER, HIDE_SALAMANDER); CreateMundaneRecipe(MOLD_ARM_MDHD, SKILL_CRAFT_ARMOR, 17, sReagentList, ARM_MDHD_SLH); // Padded Armor sReagentList = ""; CreateMundaneRecipe(MOLD_ARM_LTPD, SKILL_CRAFT_ARMOR, 2, sReagentList, ARM_LTPD_HID); } void SetUpMundaneRecipes10a() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Scale Mail sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 19, sReagentList, ARM_MDSM_ADA); // Darksteel Scale Mail sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_MDSM_DRK); // Iron Scale Mail sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 4, sReagentList, ARM_MDSM_IRN); // Mithral Scale Mail sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_MDSM_MTH); // Red Dragon Hide Scale Mail sReagentList = MakeList(HIDE_DRAGON, HIDE_DRAGON, HIDE_DRAGON); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 27, sReagentList, ARM_MDSM_RDH); // Wyvern Hide Scale Mail sReagentList = MakeList(HIDE_WYVERN, HIDE_WYVERN, HIDE_WYVERN); CreateMundaneRecipe(MOLD_ARM_MDSM, SKILL_CRAFT_ARMOR, 24, sReagentList, ARM_MDSM_WYH); // Adamantine Heavy Shield sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 17, sReagentList, ARM_SHHV_ADA); // Darksteel Heavy Shield sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 12, sReagentList, ARM_SHHV_DRK); // Duskwood Heavy Shield sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 7, sReagentList, ARM_SHHV_DSK); // Iron Heavy Shield sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 2, sReagentList, ARM_SHHV_IRN); // Mithral Heavy Shield sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 12, sReagentList, ARM_SHHV_MTH); // Umber Hulk Hide Heavy Shield sReagentList = MakeList(HIDE_UMBER_HULK, HIDE_UMBER_HULK); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 19, sReagentList, ARM_SHHV_UHH); // Zalantar Heavy Shield sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_ARM_SHHV, SKILL_CRAFT_ARMOR, 12, sReagentList, ARM_SHHV_ZAL); } void SetUpMundaneRecipes11() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Adamantine Light Shield sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 16, sReagentList, ARM_SHLT_ADA); // Darksteel Light Shield sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 11, sReagentList, ARM_SHLT_DRK); // Duskwood Light Shield sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 6, sReagentList, ARM_SHLT_DSK); // Iron Light Shield sReagentList = MakeList(INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 1, sReagentList, ARM_SHLT_IRN); // Mithral Light Shield sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 11, sReagentList, ARM_SHLT_MTH); // Umber Hulk Hide Light Shield sReagentList = MakeList(HIDE_UMBER_HULK, HIDE_UMBER_HULK); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 18, sReagentList, ARM_SHLT_UHH); // Zalantar Light Shield sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_ARM_SHLT, SKILL_CRAFT_ARMOR, 11, sReagentList, ARM_SHLT_ZAL); // Adamantine Tower Shield sReagentList = MakeList(INGOT_ADAMANTINE, INGOT_ADAMANTINE, INGOT_ADAMANTINE); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 19, sReagentList, ARM_SHTW_ADA); // Darksteel Tower Shield sReagentList = MakeList(INGOT_DARKSTEEL, INGOT_DARKSTEEL, INGOT_DARKSTEEL); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_SHTW_DRK); // Duskwood Tower Shield sReagentList = MakeList(PLANK_DUSKWOOD, PLANK_DUSKWOOD, PLANK_DUSKWOOD); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 9, sReagentList, ARM_SHTW_DSK); // Iron Tower Shield sReagentList = MakeList(INGOT_IRON, INGOT_IRON, INGOT_IRON); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 4, sReagentList, ARM_SHTW_IRN); // Mithral Tower Shield sReagentList = MakeList(INGOT_MITHRAL, INGOT_MITHRAL, INGOT_MITHRAL); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_SHTW_MTH); // Umber Hulk Hide Tower Shield sReagentList = MakeList(HIDE_UMBER_HULK, HIDE_UMBER_HULK, HIDE_UMBER_HULK); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 21, sReagentList, ARM_SHTW_UHH); // Zalantar Tower Shield sReagentList = MakeList(PLANK_ZALANTAR, PLANK_ZALANTAR, PLANK_ZALANTAR); CreateMundaneRecipe(MOLD_ARM_SHTW, SKILL_CRAFT_ARMOR, 14, sReagentList, ARM_SHTW_ZAL); } // ================================================================================= // Alchemy recipes // ================================================================================= void SetUpAlchemyRecipes1() { // Function Prototype: // void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; //Acid Flask sReagentList = MakeList(VENOM_GLAND, QUICKSILVER); CreateAlchemyRecipe(4, sReagentList, ACID_FLASK_1); //Improved Acid Flask sReagentList = MakeList(VENOM_GLAND, VENOM_GLAND, QUICKSILVER, QUICKSILVER); CreateAlchemyRecipe(8, sReagentList, ACID_FLASK_2); //Greater Acid Flask sReagentList = MakeList(VENOM_GLAND, VENOM_GLAND, VENOM_GLAND, QUICKSILVER, QUICKSILVER, QUICKSILVER); CreateAlchemyRecipe(12, sReagentList, ACID_FLASK_3); //Perfected Acid Flask sReagentList = MakeList(VENOM_GLAND, VENOM_GLAND, VENOM_GLAND, VENOM_GLAND, QUICKSILVER, QUICKSILVER, QUICKSILVER, QUICKSILVER); CreateAlchemyRecipe(16, sReagentList, ACID_FLASK_4); //Alchemists Fire sReagentList = MakeList(FAIRY_DUST, DISTILLED_ALCOHOL); CreateAlchemyRecipe(4, sReagentList, ALCHEMIST_FIRE_1); //Improved Alchemists Fire sReagentList = MakeList(FAIRY_DUST, FAIRY_DUST, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL); CreateAlchemyRecipe(8, sReagentList, ALCHEMIST_FIRE_2); } void SetUpAlchemyRecipes2() { // Function Prototype: // void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; //Greater Alchemists Fire sReagentList = MakeList(FAIRY_DUST, FAIRY_DUST, FAIRY_DUST, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL); CreateAlchemyRecipe(12, sReagentList, ALCHEMIST_FIRE_3); //Perfected Alchemists Fire sReagentList = MakeList(FAIRY_DUST, FAIRY_DUST, FAIRY_DUST, FAIRY_DUST, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL, DISTILLED_ALCOHOL); CreateAlchemyRecipe(16, sReagentList, ALCHEMIST_FIRE_4); //Choking Powder sReagentList = MakeList(BELLADONNA, GARLIC); CreateAlchemyRecipe(4, sReagentList, CHOKING_POWDER_1); //Improved Choking Powder sReagentList = MakeList(BELLADONNA, BELLADONNA, GARLIC, GARLIC); CreateAlchemyRecipe(8, sReagentList, CHOKING_POWDER_2); //Greater Choking Powder sReagentList = MakeList(BELLADONNA, BELLADONNA, BELLADONNA, GARLIC, GARLIC, GARLIC); CreateAlchemyRecipe(12, sReagentList, CHOKING_POWDER_3); //Perfected Choking Powder sReagentList = MakeList(BELLADONNA, BELLADONNA, BELLADONNA, BELLADONNA, GARLIC, GARLIC, GARLIC, GARLIC); CreateAlchemyRecipe(16, sReagentList, CHOKING_POWDER_4); } void SetUpAlchemyRecipes3() { // Function Prototype: // void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; //Holy Water sReagentList = MakeList(POWDERED_SILVER, AMETHYST); CreateAlchemyRecipe(4, sReagentList, HOLY_WATER_1); //Improved Holy Water sReagentList = MakeList(POWDERED_SILVER, POWDERED_SILVER, AMETHYST, AMETHYST); CreateAlchemyRecipe(8, sReagentList, HOLY_WATER_2); //Greater Holy Water sReagentList = MakeList(POWDERED_SILVER, POWDERED_SILVER, POWDERED_SILVER, AMETHYST, AMETHYST, AMETHYST); CreateAlchemyRecipe(12, sReagentList, HOLY_WATER_3); //Perfected Holy Water sReagentList = MakeList(POWDERED_SILVER, POWDERED_SILVER, POWDERED_SILVER, POWDERED_SILVER, AMETHYST, AMETHYST, AMETHYST, AMETHYST); CreateAlchemyRecipe(16, sReagentList, HOLY_WATER_4); //Tanglefoot Bag sReagentList = MakeList(QUICKSILVER, BELLADONNA); CreateAlchemyRecipe(4, sReagentList, TANGLEFOOT_BAG_1); //Improved Tanglefoot Bag sReagentList = MakeList(QUICKSILVER, QUICKSILVER, BELLADONNA, BELLADONNA); CreateAlchemyRecipe(8, sReagentList, TANGLEFOOT_BAG_2); } void SetUpAlchemyRecipes4() { // Function Prototype: // void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; //Greater Tanglefoot Bag sReagentList = MakeList(QUICKSILVER, QUICKSILVER, QUICKSILVER, BELLADONNA, BELLADONNA, BELLADONNA); CreateAlchemyRecipe(12, sReagentList, TANGLEFOOT_BAG_3); //Perfected Tanglefoot Bag sReagentList = MakeList(QUICKSILVER, QUICKSILVER, QUICKSILVER, QUICKSILVER, BELLADONNA, BELLADONNA, BELLADONNA, BELLADONNA); CreateAlchemyRecipe(16, sReagentList, TANGLEFOOT_BAG_4); //Thunderstone sReagentList = MakeList(DIAMOND_DUST, AMETHYST); CreateAlchemyRecipe(4, sReagentList, THUNDERSTONE_1); //Improved Thunderstone sReagentList = MakeList(DIAMOND_DUST, DIAMOND_DUST, AMETHYST, AMETHYST); CreateAlchemyRecipe(8, sReagentList, THUNDERSTONE_2); //Greater Thunderstone sReagentList = MakeList(DIAMOND_DUST, DIAMOND_DUST, DIAMOND_DUST, AMETHYST, AMETHYST, AMETHYST); CreateAlchemyRecipe(12, sReagentList, THUNDERSTONE_3); //Perfected Thunderstone sReagentList = MakeList(DIAMOND_DUST, DIAMOND_DUST, DIAMOND_DUST, DIAMOND_DUST, AMETHYST, AMETHYST, AMETHYST, AMETHYST); CreateAlchemyRecipe(16, sReagentList, THUNDERSTONE_4); } void SetUpAlchemyRecipes5() { string sReagentList; // Mild Centipede Venom sReagentList = MakeList(CENTIPEDE_GLAND); CreateAlchemyRecipe(4, sReagentList, CENTIPEDE_POISON_1); // Average Centipede Venom sReagentList = MakeList(CENTIPEDE_GLAND, CENTIPEDE_GLAND); CreateAlchemyRecipe(8, sReagentList, CENTIPEDE_POISON_2); // Strong Centipede Venom sReagentList = MakeList(CENTIPEDE_GLAND, CENTIPEDE_GLAND, CENTIPEDE_GLAND); CreateAlchemyRecipe(12, sReagentList, CENTIPEDE_POISON_3); // Deadly Centipede Venom sReagentList = MakeList(CENTIPEDE_GLAND, CENTIPEDE_GLAND, CENTIPEDE_GLAND, CENTIPEDE_GLAND); CreateAlchemyRecipe(16, sReagentList, CENTIPEDE_POISON_4); // Mild Giant Bee Venom sReagentList = MakeList(BEE_GLAND); CreateAlchemyRecipe(4, sReagentList, BEE_POISON_1); // Average Giant Bee Venom sReagentList = MakeList(BEE_GLAND, BEE_GLAND); CreateAlchemyRecipe(8, sReagentList, BEE_POISON_2); // Strong Giant Bee Venom sReagentList = MakeList(BEE_GLAND, BEE_GLAND, BEE_GLAND); CreateAlchemyRecipe(12, sReagentList, BEE_POISON_3); // Deadly Giant Bee Venom sReagentList = MakeList(BEE_GLAND, BEE_GLAND, BEE_GLAND, BEE_GLAND); CreateAlchemyRecipe(16, sReagentList, BEE_POISON_4); // Weak Scorpion Venom sReagentList = MakeList(SCORPION_GLAND); CreateAlchemyRecipe(4, sReagentList, SCORPION_POISON_1); // Average Scorpion Venom sReagentList = MakeList(SCORPION_GLAND, SCORPION_GLAND); CreateAlchemyRecipe(8, sReagentList, SCORPION_POISON_2); // Strong Scorpion Venom sReagentList = MakeList(SCORPION_GLAND, SCORPION_GLAND, SCORPION_GLAND); CreateAlchemyRecipe(12, sReagentList, SCORPION_POISON_3); // Deadly Scorpion Venom sReagentList = MakeList(SCORPION_GLAND, SCORPION_GLAND, SCORPION_GLAND, SCORPION_GLAND); CreateAlchemyRecipe(16, sReagentList, SCORPION_POISON_4); } // Alchemy recipes for coalescing essences. const int NUM_ESSENCES_FOR_COALESCENCE = 2; const int WEAK_COALESCENCE_SKILL = 5; const int GLOWING_COALESCENCE_SKILL = 10; const int RADIANT_COALESCENCE_SKILL = 15; void SetUpAlchemyRecipes6() { // Function Prototype: // void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // AIR 1 -> AIR 2 sReagentList = MakeRepeatedItemList(AIR1, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(WEAK_COALESCENCE_SKILL, sReagentList, AIR2); // AIR 2 -> AIR 3 sReagentList = MakeRepeatedItemList(AIR2, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(GLOWING_COALESCENCE_SKILL, sReagentList, AIR3); // AIR 3 -> AIR 4 sReagentList = MakeRepeatedItemList(AIR3, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(RADIANT_COALESCENCE_SKILL, sReagentList, AIR4); // WATER 1 -> WATER 2 sReagentList = MakeRepeatedItemList(WATER1, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(WEAK_COALESCENCE_SKILL, sReagentList, WATER2); // WATER 2 -> WATER 3 sReagentList = MakeRepeatedItemList(WATER2, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(GLOWING_COALESCENCE_SKILL, sReagentList, WATER3); // WATER 3 -> WATER 4 sReagentList = MakeRepeatedItemList(WATER3, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(RADIANT_COALESCENCE_SKILL, sReagentList, WATER4); // FIRE 1 -> FIRE 2 sReagentList = MakeRepeatedItemList(FIRE1, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(WEAK_COALESCENCE_SKILL, sReagentList, FIRE2); // FIRE 2 -> FIRE 3 sReagentList = MakeRepeatedItemList(FIRE2, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(GLOWING_COALESCENCE_SKILL, sReagentList, FIRE3); // FIRE 3 -> FIRE 4 sReagentList = MakeRepeatedItemList(FIRE3, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(RADIANT_COALESCENCE_SKILL, sReagentList, FIRE4); // EARTH 1 -> EARTH 2 sReagentList = MakeRepeatedItemList(EARTH1, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(WEAK_COALESCENCE_SKILL, sReagentList, EARTH2); // EARTH 2 -> EARTH 3 sReagentList = MakeRepeatedItemList(EARTH2, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(GLOWING_COALESCENCE_SKILL, sReagentList, EARTH3); // EARTH 3 -> EARTH 4 sReagentList = MakeRepeatedItemList(EARTH3, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(RADIANT_COALESCENCE_SKILL, sReagentList, EARTH4); // POWER 1 -> POWER 2 sReagentList = MakeRepeatedItemList(POWER1, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(WEAK_COALESCENCE_SKILL, sReagentList, POWER2); // POWER 2 -> POWER 3 sReagentList = MakeRepeatedItemList(POWER2, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(GLOWING_COALESCENCE_SKILL, sReagentList, POWER3); // POWER 3 -> POWER 4 sReagentList = MakeRepeatedItemList(POWER3, NUM_ESSENCES_FOR_COALESCENCE); CreateAlchemyRecipe(RADIANT_COALESCENCE_SKILL, sReagentList, POWER4); } // ================================================================================= // Distillation recipes // ================================================================================= void SetUpDistillationRecipes1() { // Function Prototype: // void CreateDistillationRecipe(int iSkillLevel, string sReagent, string sOutputResRefList); string sOutputList; //string sRandomEssence; //string sRandomEssenceHigh; //Bladeling Spike CreateDistillationRecipe(4, BLADELING_SPIKE, POWER1); //Bat Tooth CreateDistillationRecipe(4, BAT_TOOTH, AIR1); //Bear Claw CreateDistillationRecipe(6, BEAR_CLAW, EARTH2); //Dire Bear Claw CreateDistillationRecipe(8, DIRE_BEAR_CLAW, EARTH3); //Beetle Gland CreateDistillationRecipe(6, BEETLE_GLAND, EARTH2); //Fire Beetle Belly CreateDistillationRecipe(6, FIRE_BEETLE_BELLY, FIRE2); //Stag Beetle Horn CreateDistillationRecipe(4, STAG_BEETLE_HORN, EARTH1); //Dire Boar Tusk CreateDistillationRecipe(4, DIRE_BOAR_TUSK, EARTH1); //Bugbear Tusk CreateDistillationRecipe(8, BUGBEAR_TUSK, WATER3); //Demon Blood sOutputList = MakeList(POWER3, FIRE1); CreateDistillationRecipe(8, DEMON_BLOOD, sOutputList); //Devil Blood sOutputList = MakeList(POWER3, FIRE1); CreateDistillationRecipe(8, DEVIL_BLOOD, sOutputList); //Dragon Blood CreateDistillationRecipe(10, DRAGON_BLOOD, POWER4); //Gargoyle Horn CreateDistillationRecipe(6, GARGOYLE_HORN, EARTH2); //Ghoul Claws sOutputList = MakeList(AIR2, POWER1); CreateDistillationRecipe(6, GHOUL_CLAWS, sOutputList); //Ghast Claws sOutputList = MakeList(AIR3, POWER2); CreateDistillationRecipe(8, GHAST_CLAWS, sOutputList); //Ghost Residue CreateDistillationRecipe(8, GHOST_RESIDUE, AIR3); } // ================================================================================= // Distillation recipes // ================================================================================= void SetUpDistillationRecipes2() { // Function Prototype: // void CreateDistillationRecipe(int iSkillLevel, string sReagent, string sOutputResRefList); string sOutputList; //string sRandomEssence; //string sRandomEssenceHigh; //Fire Giant Head CreateDistillationRecipe(10, FIRE_GIANT_HEAD, FIRE4); //Frost Giant Head CreateDistillationRecipe(10, FROST_GIANT_HEAD, WATER4); //Iron Golem Fragments CreateDistillationRecipe(10, IRON_GOLEM_FRAGMENTS, EARTH4); //Hellhound Tooth CreateDistillationRecipe(8, HELLHOUND_TOOTH, FIRE3); //Imp Tail CreateDistillationRecipe(4, IMP_TAIL, FIRE1); //Lich Dust sOutputList = MakeList(POWER4, AIR4); CreateDistillationRecipe(10, LICH_DUST, sOutputList); //Fire Mephit Hide CreateDistillationRecipe(6, FIRE_MEPHIT_HIDE, FIRE2); //Ice Mephit Hide CreateDistillationRecipe(6, ICE_MEPHIT_HIDE, WATER2); //Ogre Mage Skull CreateDistillationRecipe(8, OGRE_MAGE_SKULL, POWER3); //Shadow Residue CreateDistillationRecipe(8, SHADOW_RESIDUE, AIR4); //Skeleton Knuckle CreateDistillationRecipe(4, SKELETON_KNUCKLE, EARTH1); //Spider Venom Gland CreateDistillationRecipe(6, SPIDER_VENOM_GLAND, WATER2); //Phase Spider Mandible sOutputList = MakeList(POWER3, WATER3); CreateDistillationRecipe(8, PHASE_SPIDER_MANDIBLE, sOutputList); //Blade Spider Leg CreateDistillationRecipe(8, SWORD_SPIDER_LEG, EARTH3); //Troll Blood sOutputList = MakeList(POWER2, WATER2); CreateDistillationRecipe(6, TROLL_BLOOD, sOutputList); //Umber Hulk Mandible sOutputList = MakeList(POWER1, WATER2); CreateDistillationRecipe(6, UMBER_HULK_MANDIBLE, sOutputList); //Vampire Tooth sOutputList = MakeList(POWER3, FIRE3); CreateDistillationRecipe(8, VAMPIRE_TOOTH, sOutputList); //Dire Wolf Tooth CreateDistillationRecipe(4, DIRE_WOLF_TOOTH, WATER1); //Winter Wolf Pelt CreateDistillationRecipe(8, WINTER_WOLF_PELT, WATER3); //Wraith Residue sOutputList = MakeList(POWER2, AIR2); CreateDistillationRecipe(6, WRAITH_RESIDUE, sOutputList); //Wyvern Scale CreateDistillationRecipe(6, WYVERN_SCALE, AIR2); //Crystal Heart sOutputList = MakeList(POWER4, AIR4, WATER4); CreateDistillationRecipe(10, CRYSTAL_HEART, sOutputList); } // ================================================================================= // Distillation recipes // ================================================================================= void SetUpDistillationRecipes3() { // Function Prototype: // void CreateDistillationRecipe(int iSkillLevel, string sReagent, string sOutputResRefList); string sOutputList; //string sRandomEssence; //string sRandomEssenceHigh; //Faint Air Essence CreateDistillationRecipe(4, AIR2, AIR1); //Weak Air Essence CreateDistillationRecipe(6, AIR3, AIR2); //Glowing Air Essence CreateDistillationRecipe(8, AIR4, AIR3); //Faint Earth Essence CreateDistillationRecipe(4, EARTH2, EARTH1); //Weak Earth Essence CreateDistillationRecipe(6, EARTH3, EARTH2); //Glowing Earth Essence CreateDistillationRecipe(8, EARTH4, EARTH3); //Faint Fire Essence CreateDistillationRecipe(4, FIRE2, FIRE1); //Weak Fire Essence CreateDistillationRecipe(6, FIRE3, FIRE2); //Glowing Fire Essence CreateDistillationRecipe(8, FIRE4, FIRE3); //Faint Water Essence CreateDistillationRecipe(4, WATER2, WATER1); //Weak Water Essence CreateDistillationRecipe(6, WATER3, WATER2); //Glowing Water Essence CreateDistillationRecipe(8, WATER4, WATER3); //Faint Power Essence CreateDistillationRecipe(4, POWER2, POWER1); //Weak Power Essence CreateDistillationRecipe(6, POWER3, POWER2); //Glowing Power Essence CreateDistillationRecipe(8, POWER4, POWER3); } const string MOLD_TRAP_KIT = "n2_crft_mold_trap"; const string TRAP_FIRE_COMPONENT = "X1_WMGRENADE002"; // alchemists fire const string TRAP_ELECTRICAL_COMPONENT = "NW_IT_MSMLMISC11"; // quartz crystal const string TRAP_TANGLE_COMPONENT = "X1_WMGRENADE006"; // tanglefoot bag const string TRAP_SPIKE_COMPONENT = "NW_WSWDG001"; // dagger const string TRAP_HOLY_COMPONENT = "X1_WMGRENADE005"; // holy water const string TRAP_GAS_COMPONENT = "X1_WMGRENADE004"; // choking powder const string TRAP_FROST_COMPONENT = "X1_IT_MSMLMISC01"; // coldstone const string TRAP_NEGATIVE_COMPONENT = "cft_gem_03"; // Obsidian const string TRAP_SONIC_COMPONENT = "X1_WMGRENADE007"; // thunderstone const string TRAP_ACID_COMPONENT = "X1_WMGRENADE001"; // acid flask const string TRAP_ACID_BLOB_COMPONENT = "X1_WMGRENADE001, X1_WMGRENADE006"; //ACID FLASK AND TANGLEFOOT BAG // the number of components required for each trap type const int TRAP_COMPONENT_COUNT_MINOR = 1; const int TRAP_COMPONENT_COUNT_AVERAGE = 3; const int TRAP_COMPONENT_COUNT_STRONG = 5; const int TRAP_COMPONENT_COUNT_DEADLY = 7; const string SPIKE_TRAP_KIT_MINOR = "nw_it_trap001"; const string SPIKE_TRAP_KIT_AVERAGE = "nw_it_trap002"; const string SPIKE_TRAP_KIT_STRONG = "nw_it_trap003"; const string SPIKE_TRAP_KIT_DEADLY = "nw_it_trap004"; const string HOLY_TRAP_KIT_MINOR = "nw_it_trap005"; const string HOLY_TRAP_KIT_AVERAGE = "nw_it_trap006"; const string HOLY_TRAP_KIT_STRONG = "nw_it_trap007"; const string HOLY_TRAP_KIT_DEADLY = "nw_it_trap008"; const string TANGLE_TRAP_KIT_MINOR = "nw_it_trap009"; const string TANGLE_TRAP_KIT_AVERAGE = "nw_it_trap010"; const string TANGLE_TRAP_KIT_STRONG = "nw_it_trap011"; const string TANGLE_TRAP_KIT_DEADLY = "nw_it_trap012"; const string ACID_BLOB_TRAP_KIT_MINOR = "nw_it_trap013"; const string ACID_BLOB_TRAP_KIT_AVERAGE = "nw_it_trap014"; const string ACID_BLOB_TRAP_KIT_STRONG = "nw_it_trap015"; const string ACID_BLOB_TRAP_KIT_DEADLY = "nw_it_trap016"; const string FIRE_TRAP_KIT_MINOR = "nw_it_trap017"; const string FIRE_TRAP_KIT_AVERAGE = "nw_it_trap018"; const string FIRE_TRAP_KIT_STRONG = "nw_it_trap019"; const string FIRE_TRAP_KIT_DEADLY = "nw_it_trap020"; const string ELECTRICAL_TRAP_KIT_MINOR = "nw_it_trap021"; const string ELECTRICAL_TRAP_KIT_AVERAGE = "nw_it_trap022"; const string ELECTRICAL_TRAP_KIT_STRONG = "nw_it_trap023"; const string ELECTRICAL_TRAP_KIT_DEADLY = "nw_it_trap024"; const string GAS_TRAP_KIT_MINOR = "nw_it_trap025"; const string GAS_TRAP_KIT_AVERAGE = "nw_it_trap026"; const string GAS_TRAP_KIT_STRONG = "nw_it_trap027"; const string GAS_TRAP_KIT_DEADLY = "nw_it_trap028"; const string FROST_TRAP_KIT_MINOR = "nw_it_trap029"; const string FROST_TRAP_KIT_AVERAGE = "nw_it_trap030"; const string FROST_TRAP_KIT_STRONG = "nw_it_trap031"; const string FROST_TRAP_KIT_DEADLY = "nw_it_trap032"; const string ACID_SPLASH_TRAP_KIT_MINOR = "nw_it_trap033"; const string ACID_SPLASH_TRAP_KIT_AVERAGE = "nw_it_trap034"; const string ACID_SPLASH_TRAP_KIT_STRONG = "nw_it_trap035"; const string ACID_SPLASH_TRAP_KIT_DEADLY = "nw_it_trap036"; const string SONIC_TRAP_KIT_MINOR = "nw_it_trap037"; const string SONIC_TRAP_KIT_AVERAGE = "nw_it_trap038"; const string SONIC_TRAP_KIT_STRONG = "nw_it_trap039"; const string SONIC_TRAP_KIT_DEADLY = "nw_it_trap040"; const string NEGATIVE_TRAP_KIT_MINOR = "nw_it_trap041"; const string NEGATIVE_TRAP_KIT_AVERAGE = "nw_it_trap042"; const string NEGATIVE_TRAP_KIT_STRONG = "nw_it_trap043"; const string NEGATIVE_TRAP_KIT_DEADLY = "nw_it_trap044"; void SetUpTraps1() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Spike Traps sReagentList = MakeRepeatedItemList (TRAP_SPIKE_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, SPIKE_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_SPIKE_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, SPIKE_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_SPIKE_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, SPIKE_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_SPIKE_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, SPIKE_TRAP_KIT_DEADLY); // Holy Traps sReagentList = MakeRepeatedItemList (TRAP_HOLY_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, HOLY_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_HOLY_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, HOLY_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_HOLY_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, HOLY_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_HOLY_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, HOLY_TRAP_KIT_DEADLY); // Tangle Traps sReagentList = MakeRepeatedItemList (TRAP_TANGLE_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, TANGLE_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_TANGLE_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, TANGLE_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_TANGLE_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, TANGLE_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_TANGLE_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, TANGLE_TRAP_KIT_DEADLY); } void SetUpTraps2() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Acid Blob Traps sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, ACID_BLOB_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, ACID_BLOB_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, ACID_BLOB_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, ACID_BLOB_TRAP_KIT_DEADLY); // Fire Traps sReagentList = MakeRepeatedItemList (TRAP_FIRE_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, FIRE_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_FIRE_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, FIRE_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_FIRE_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, FIRE_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_FIRE_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, FIRE_TRAP_KIT_DEADLY); // Electrical Traps sReagentList = MakeRepeatedItemList (TRAP_ELECTRICAL_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, ELECTRICAL_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_ELECTRICAL_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, ELECTRICAL_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_ELECTRICAL_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, ELECTRICAL_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_ELECTRICAL_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, ELECTRICAL_TRAP_KIT_DEADLY); } void SetUpTraps3() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Gas Traps sReagentList = MakeRepeatedItemList (TRAP_GAS_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, GAS_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_GAS_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, GAS_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_GAS_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, GAS_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_GAS_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, GAS_TRAP_KIT_DEADLY); // Frost Traps sReagentList = MakeRepeatedItemList (TRAP_FROST_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, FROST_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_FROST_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, FROST_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_FROST_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, FROST_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_FROST_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, FROST_TRAP_KIT_DEADLY); // Acid Splash Traps sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, ACID_SPLASH_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, ACID_SPLASH_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, ACID_SPLASH_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_ACID_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, ACID_SPLASH_TRAP_KIT_DEADLY); } void SetUpTraps4() { // Function Prototype: // void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); string sReagentList; // Sonic Traps sReagentList = MakeRepeatedItemList (TRAP_SONIC_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, SONIC_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_SONIC_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, SONIC_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_SONIC_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, SONIC_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_SONIC_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, SONIC_TRAP_KIT_DEADLY); // Negative Traps sReagentList = MakeRepeatedItemList (TRAP_NEGATIVE_COMPONENT, TRAP_COMPONENT_COUNT_MINOR); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 5, sReagentList, NEGATIVE_TRAP_KIT_MINOR); sReagentList = MakeRepeatedItemList (TRAP_NEGATIVE_COMPONENT, TRAP_COMPONENT_COUNT_AVERAGE); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 10, sReagentList, NEGATIVE_TRAP_KIT_AVERAGE); sReagentList = MakeRepeatedItemList (TRAP_NEGATIVE_COMPONENT, TRAP_COMPONENT_COUNT_STRONG); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 15, sReagentList, NEGATIVE_TRAP_KIT_STRONG); sReagentList = MakeRepeatedItemList (TRAP_NEGATIVE_COMPONENT, TRAP_COMPONENT_COUNT_DEADLY); CreateMundaneRecipe(MOLD_TRAP_KIT, SKILL_CRAFT_TRAP, 20, sReagentList, NEGATIVE_TRAP_KIT_DEADLY); } // ================================================================================= // main // ================================================================================= void main() { // object oPC = GetLastUsedBy(); // if (oPC == OBJECT_INVALID) // oPC = GetEnteringObject(); // only set up recipies once if (GetGlobalInt(VAR_REC_SET) == TRUE) { output("Recipies already set!"); return; } // These functions set up all the recipes into global memory int iSetupCount = ModifyGlobalInt("SETUP_COUNT", 1); int bDone = FALSE; output("Setting up Recipe set " + IntToString(iSetupCount) + "..."); switch (iSetupCount) { case 1: // armor 1 SetUpMagicalRecipes1(); break; case 2: // armor 2 SetUpMagicalRecipes2(); break; case 3: // weapon 1 SetUpMagicalRecipes3(); break; case 4: // weapon 2 SetUpMagicalRecipes4(); break; case 5: // Wondrous 1 of 3 SetUpWondrousRecipes1(); break; case 6: // Wondrous 2 of 3 SetUpWondrousRecipes2(); break; case 7: // Wondrous 3 of 3 SetUpWondrousRecipes3(); break; case 8: // Mundane Recipes 1 of 11 SetUpMundaneRecipes1(); break; case 9: // Mundane Recipes 2 of 11 SetUpMundaneRecipes2(); break; case 10: // Mundane Recipes 3 of 11 SetUpMundaneRecipes3(); break; case 11: // Mundane Recipes 4 of 11 SetUpMundaneRecipes4(); break; case 12: // Mundane Recipes 5 of 11 SetUpMundaneRecipes5(); break; case 13: // Mundane Recipes 6 of 11 SetUpMundaneRecipes6(); break; case 14: // Mundane Recipes 7 of 11 SetUpMundaneRecipes7(); break; case 15: // Mundane Recipes 8 of 11 SetUpMundaneRecipes8(); break; case 16: // Mundane Recipes 9 of 11 SetUpMundaneRecipes9(); break; case 17: // Mundane Recipes 9 of 11 SetUpMundaneRecipes9a(); break; case 18: // Mundane Recipes 10 of 11 SetUpMundaneRecipes10(); break; case 19: // Mundane Recipes 10 of 11 SetUpMundaneRecipes10a(); break; case 20: // Mundane Recipes 11 of 11 SetUpMundaneRecipes11(); break; case 21: // Alchemy 1 SetUpAlchemyRecipes1(); break; case 22: // Alchemy 2 SetUpAlchemyRecipes2(); break; case 23: // Alchemy 3 SetUpAlchemyRecipes3(); break; case 24: // Alchemy 4 SetUpAlchemyRecipes4(); break; case 25: // Distillation 1 SetUpDistillationRecipes1(); break; case 26: // Distillation 2 SetUpDistillationRecipes2(); break; case 27: // Distillation 3 SetUpDistillationRecipes3(); break; case 28: // Trap 1 SetUpTraps1(); break; case 29: // Trap 2 SetUpTraps2(); break; case 30: // Trap 3 SetUpTraps3(); break; case 31: // Trap 4 SetUpTraps4(); break; case 32: // Alchemy 5 (Poison) SetUpAlchemyRecipes5(); break; case 33: //Wondrous 3a SetUpWondrousRecipes3a(); break; case 34: //Wondrous 3b SetUpWondrousRecipes3b(); break; case 35: // Coalescing Essence Alchemy Recipes SetUpAlchemyRecipes6(); break; case 36: // the flails SetUpStandardMetalItem(MOLD_WPN_FLAIL, 1, 2, WPN_FLAIL_ADA, WPN_FLAIL_CLD, WPN_FLAIL_DRK, WPN_FLAIL_IRN, WPN_FLAIL_MTH, WPN_FLAIL_SLV); default: SetGlobalInt(VAR_REC_SET, TRUE); bDone = TRUE; output("Recipes now loaded in Global Memory. Crafting now based on Global Memory set up for this session."); output("Recipe data can be exported to 2da format in the log by stepping into designated area."); } output("Script completed."); if (!bDone) { DelayCommand(0.2f, ExecuteScript("ga_setrecipes", OBJECT_SELF)); } } // ga_sound_object_play(string sTarget) /* plays a sound object, which may comprise many sound resources Parameters: string sTarget = tag of the sound object */ //ChazM 8/17/06 #include "ginc_param_const" void main(string sTarget) { object oTarget = GetSoundObjectByTag(sTarget); if (GetIsObjectValid(oTarget)) SoundObjectPlay(oTarget); } // ga_sound_object_set_position(string sTarget, string sPositionTag, float fXoffset, float fYoffset, float fZoffset) /* Sets the position of a sound object. Sound Object will play at the tag of the object specified. A vector offset can be specified to fine tune the placement. A vector offset can be set relative to the origin of the area by leaving sPositionTag blank. Parameters: string sTarget = tag of the sound object string sPositionTag = tag of an object to use as the position. not required. float fXoffset, float fYoffset, float fZoffset = vector offest to the sPositionTag. */ //ChazM 8/17/06 #include "ginc_param_const" void main(string sTarget, string sPositionTag, float fXoffset, float fYoffset, float fZoffset) { object oTarget = GetSoundObjectByTag(sTarget); if (GetIsObjectValid(oTarget)) { object oPositionTarget = OBJECT_INVALID; if (sPositionTag != "") { oPositionTarget = GetTarget(sPositionTag); } //if (GetIsObjectValid (oPositionTarget)) vector vPosition = GetPosition(oPositionTarget); // returns 0 vector if object invalid vector vOffset = Vector(fXoffset, fYoffset, fZoffset); vPosition = vPosition + vOffset; SoundObjectSetPosition(oTarget, vPosition); } } // ga_sound_object_set_volume(string sTarget, int iVolume) /* Sets the volume of a placed sound object Parameters: string sTarget = tag of the sound object int iVolue = An integer value between 0 and 127 */ //ChazM 8/17/06 #include "ginc_param_const" void main(string sTarget, int iVolume) { object oTarget = GetSoundObjectByTag(sTarget); if (GetIsObjectValid(oTarget)) SoundObjectSetVolume(oTarget, iVolume); } // ga_sound_object_stop(string sTarget) /* Stops a sound object from playing Parameters: string sTarget = tag of the sound object */ //ChazM 8/17/06 #include "ginc_param_const" void main(string sTarget) { object oTarget = GetSoundObjectByTag(sTarget); if (GetIsObjectValid(oTarget)) SoundObjectStop(oTarget); } // ga_start_convo /* This script starts a new conversation. Handy when you want to jump directly from one conversation to another. Parameters: string sTarget = Target who will start convo with the PC string sConversation = Params are all from ActionStartConversation() int bPrivateConversation int bPlayHello int bIgnoreStartDistance int bDisableCutsceneBars */ // ChazM 9/14/05 // ChazM 9/20/06 - fixed inc. #include "ginc_param_const" void main(string sTarget, string sConversation, int bPrivateConversation, int bPlayHello, int bIgnoreStartDistance, int bDisableCutsceneBars) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oTarget = GetTarget(sTarget); AssignCommand(oTarget, ActionStartConversation(oPC, sConversation, bPrivateConversation, bPlayHello, bIgnoreStartDistance, bDisableCutsceneBars)); } // ga_start_mod(string sModuleName) /* Starts a new module Parameters: string sModuleName = The file name of the module to start. Act 1 Modules: 1000_Neverwinter_A1 1100_West_Harbor 1200_Highcliff 1300_Old_Owl_Well 1400_Neverwinter_Wood 1600_Githyanki_Caves */ // ChazM 7/25/05 void main(string sModuleName) { StartNewModule(sModuleName); } // ga_take_gold /* This takes gold from a player nGold = The amount of gold to take nAllPCs = If set to 1 it takes gold from all PCs (MP only) */ // FAB 4/28/05 void main(int nGold, int nAllPCs) { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); if ( nAllPCs == 0 ) { TakeGoldFromCreature( nGold,oPC ); } else {// For multiple players oPC = GetFirstPC(); while ( GetIsObjectValid(oPC) ) { TakeGoldFromCreature( nGold,oPC ); oPC = GetNextPC(); } } } // ga_take_item /* This takes an item from a player sItemTag = This is the string name of the item's tag nQuantity = The number of items (default is 1). -1 is all of the Player's items of that tag. nAllPCs = If set to 1 it gives the item to all PCs (MP only) */ // FAB 9/30 #include "nw_i0_plot" void main(string sItemTag, int nQuantity, int nAllPCs) { int nTotalItem; object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oItem; // Items in inventory if ( nQuantity == 0 ) nQuantity = 1; if ( nAllPCs == 0 ) { if ( nQuantity < 0 ) // Destroy all instances of the item { nTotalItem = GetNumItems( oPC,sItemTag ); TakeNumItems( oPC,sItemTag,nTotalItem ); } else { TakeNumItems( oPC,sItemTag,nQuantity ); } } else // For multiple players { oPC = GetFirstPC(); while ( GetIsObjectValid(oPC) ) { if ( nQuantity < 0 ) // Destroy all instances of the item { nTotalItem = GetNumItems( oPC,sItemTag ); TakeNumItems( oPC,sItemTag,nTotalItem ); } else { TakeNumItems( oPC,sItemTag,nQuantity ); } oPC = GetNextPC(); } } } // ga_talkto(string sTarget) /* Set "TalkedTo" flag that you have talked to the target. Parameters: string sTarget = Tag of the NPC. If blank, use OBJECT_SELF. */ // FAB 9/30 // BMA 4/28/05 added GetTarget() #include "ginc_param_const" void main(string sTarget) { object oTarget = GetTarget(sTarget, TARGET_OBJECT_SELF); SetLocalInt(oTarget, "TalkedTo", 1); } // ga_time_advance /* Advance time by amount indicated Time can only be advanced forwards; attempting to set the time backwards will result in the day advancing and then the time being set to that specified. nHour - The number of hours to advance. nMinute - The number of Minutes to advance. nSecond - The number of Seconds to advance. nMillisecond - The number of Milliseconds to advance. */ // ChazM 6/27/06 void main(int nHour, int nMinute, int nSecond, int nMillisecond) { nHour = GetTimeHour() + nHour; nMinute = GetTimeMinute() + nMinute; nSecond = GetTimeSecond() + nSecond; nMillisecond = GetTimeMillisecond() + nMillisecond; // Set the new time SetTime(nHour, nMinute, nSecond, nMillisecond); } // ga_time_set /* Set time to to value indicated. Time can only be advanced forwards; attempting to set the time backwards will result in the day advancing and then the time being set to that specified. nHour - The new hour value, from 0 to 23. nMinute - The new minute value from 0 to 1 (or 0 to a higher value if the module properties for time were changed). nSecond - The new second value, from 0 to 59. nMillisecond - The new millisecond value, from 0 to 999. */ // ChazM 6/27/06 void main(int nHour, int nMinute, int nSecond, int nMillisecond) { // Set the new time SetTime(nHour, nMinute, nSecond, nMillisecond); } // ga_unequip_hands /* unequip hands, and mark items so they can be restored */ // ChazM 6/27/06 // EPF 8/29/06 - uneqip offhand before main hand, else the offhand weapon is switched to the main // hand by the engine. #include "ginc_param_const" #include "ginc_item" void main(string sOwner) { object oOwner = GetTarget(sOwner); RememberEquippedItem(oOwner, INVENTORY_SLOT_LEFTHAND); UnequipSlot(oOwner, INVENTORY_SLOT_LEFTHAND); RememberEquippedItem(oOwner, INVENTORY_SLOT_RIGHTHAND); UnequipSlot(oOwner, INVENTORY_SLOT_RIGHTHAND); } Global Artificial Intellegence // gb_attack_caster_ai // // Attack casters first. Then ranged. Then melee. // EPF 8/18/06 #include "ginc_ai" void main() { AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_CLASS_PRIORITY); AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_SPELLCASTERS ); //first class to attack.. AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_RANGED ); //second.. AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_MELEE ); //so on.. } // gb_attack_melee_ai // // Attack melee first, then casters, then ranged. // EPF 8/18/06 #include "ginc_ai" void main() { AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_CLASS_PRIORITY); AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_MELEE ); //so on.. AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_SPELLCASTERS ); //first class to attack.. AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_RANGED ); //second.. } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_blockedcount_b //:: //:: Tallies how many times we've been blocked. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/1/06 #include "ginc_ai" //#include "ginc_debug" void main() { int nBlockCount=GetLocalInt(OBJECT_SELF, VAR_AP_BLOCKCOUNT); if (nBlockCount>=0) SetLocalInt(OBJECT_SELF, VAR_AP_BLOCKCOUNT, nBlockCount + 1 ); AIContinueInterruptedScript(CREATURE_SCRIPT_ON_BLOCKED_BY_DOOR); //this script is an interrupt script, so this must be called //when you want the original to play } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_counterspell_dcr //:: //:: Determine Combat Round for the Spell Queue AI. //:: //:: Spell Queue AI's will cast spells form an ordered list attached to them. //:: To Attach a list, use the function ******, the conversation script ******, //:: or manually using these variables (must be done pre-spawn) *******. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "nw_i0_generic" #include "x2_inc_switches" #include "ginc_param_const" #include "ginc_ai" #include "nw_i0_plot" //#include "ginc_debug" object GetSuitableSpellCaster() { object oWiz=GetNearestCreature(CREATURE_TYPE_CLASS,CLASS_TYPE_WIZARD,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_IS_ALIVE,TRUE); object oSor=GetNearestCreature(CREATURE_TYPE_CLASS,CLASS_TYPE_SORCERER,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_IS_ALIVE,TRUE); if (!GetIsObjectValid(oWiz)) return oSor; if (!GetIsObjectValid(oSor)) return oWiz; if ((GetDistanceBetween(OBJECT_SELF,oSor))<(GetDistanceBetween(OBJECT_SELF,oWiz))) return oSor; else return oWiz; } void main() { object oIntruder = GetCreatureOverrideAIScriptTarget(); ClearCreatureOverrideAIScriptTarget(); //Handling Determine Combat round red tape int nDebuf=-1; if (GetHasSpell(SPELL_GREATER_DISPELLING)) nDebuf=SPELL_GREATER_DISPELLING; else if (GetHasSpell(SPELL_DISPEL_MAGIC)) nDebuf=SPELL_DISPEL_MAGIC; else if (GetHasSpell(SPELL_LESSER_DISPEL)) nDebuf=SPELL_LESSER_DISPEL; if (nDebuf!=-1) { //check for enemy buffs object oTemp,oCaster; int i=0; float fDist=0.0f; effect eFX; while ((fDist<13.0f) && (GetIsObjectValid(oTemp=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE)))) { fDist=GetDistanceBetween(OBJECT_SELF,oTemp); eFX=GetFirstEffect(oTemp); while(GetIsEffectValid(eFX)) { oCaster=GetEffectCreator(eFX); if (GetReputation(oCaster,oTemp)>10) //if they are friends... probably a buff. { // PrettyMessage("Debuffing!"); __TurnCombatRoundOn(TRUE); ActionCastSpellAtObject(nDebuf,oTemp,METAMAGIC_ANY); __TurnCombatRoundOn(FALSE); SetCreatureOverrideAIScriptFinished();//Tell Determine Combat Round That I handled things. return; } eFX=GetNextEffect(oTemp); } } // //ok, no buffs. Go in Counterspell mode for nearby spellcasters object oSpellCaster=GetSuitableSpellCaster(); if ((GetDistanceBetween(oSpellCaster,OBJECT_SELF)>10.0f)||(!GetIsObjectValid(oSpellCaster))) return;//standard DCR else if (!GetActionMode(OBJECT_SELF,ACTION_MODE_COUNTERSPELL)) { // PrettyDebug("Trying to perform CounterSpell on: " + GetTag(oSpellCaster)); SetActionMode(OBJECT_SELF,ACTION_MODE_COUNTERSPELL,TRUE); __TurnCombatRoundOn(TRUE); ActionCounterSpell(oSpellCaster); __TurnCombatRoundOn(FALSE); SetCreatureOverrideAIScriptFinished();//Tell Determine Combat Round That I handled things. return; } } //otherwise standard DCR } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_damagetracker_b //:: //:: Tracks those who have hurt me, much like my lists of names from high school. //:: from ginc_ai, used by the "attack who damaged me most" AI type //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/1/06 #include "ginc_ai" //#include "ginc_debug" int GetCreatureIndex(object oDamager); void BSortDown(int index); void main() { object oDamager=GetLastDamager(); int nDamage = GetTotalDamageDealt(); // PrettyMessage(GetTag(oDamager) + " Has hit me for " + IntToString(nDamage)); int index = GetCreatureIndex(oDamager); //increase totaled damage count SetLocalInt(OBJECT_SELF, VAR_AP_DAMAGER_PTS + IntToString(index), GetLocalInt(OBJECT_SELF,VAR_AP_DAMAGER_PTS+IntToString(index))+nDamage); if (index>1) BSortDown(index); AIContinueInterruptedScript(CREATURE_SCRIPT_ON_DAMAGED); //this script is an interrupt script, so this must be called //when you want the original to play } void BSortDown(int index) { int nVal = GetLocalInt(OBJECT_SELF,VAR_AP_DAMAGER_PTS+IntToString(index)); int nNextVal = GetLocalInt(OBJECT_SELF,VAR_AP_DAMAGER_PTS+IntToString(index-1)); if (nVal>nNextVal)//swap me down one { object oMe=GetLocalObject(OBJECT_SELF,VAR_AP_DAMAGER+IntToString(index)); object oNext=GetLocalObject(OBJECT_SELF,VAR_AP_DAMAGER+IntToString(index-1)); SetLocalObject(OBJECT_SELF,VAR_AP_DAMAGER+IntToString(index-1),oMe); SetLocalObject(OBJECT_SELF,VAR_AP_DAMAGER+IntToString(index),oNext); SetLocalInt(OBJECT_SELF,VAR_AP_DAMAGER_PTS+IntToString(index-1),nVal); SetLocalInt(OBJECT_SELF,VAR_AP_DAMAGER_PTS+IntToString(index),nNextVal); } if (index>2)//reursive, unless we're at the beginning of the list BSortDown(index-1); } int GetCreatureIndex(object oDamager) { int i=0; int nNumEntries=GetLocalInt(OBJECT_SELF,VAR_AP_NUM_DAMAGERS); while (i GetLocalFloat(OBJECT_SELF,VAR_FP_MAXDIST)) { // PrettyDebug("I should be going home now"); ClearAllActions(TRUE); __TurnCombatRoundOn(TRUE); ActionMoveToLocation(lHomebase,TRUE); __TurnCombatRoundOn(FALSE); ActionWait(2.0f); ActionDoCommand(DetermineCombatRound()); SetCreatureOverrideAIScriptFinished(); //Running back home, DCR can stop } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_ignore_dcr //:: //:: Determine Combat Round for the Spell Queue AI. //:: //:: Spell Queue AI's will cast spells form an ordered list attached to them. //:: To Attach a list, use the function ******, the conversation script ******, //:: or manually using these variables (must be done pre-spawn) *******. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { object oIntruder = GetCreatureOverrideAIScriptTarget(); ClearCreatureOverrideAIScriptTarget(); //Handling Determine Combat round red tape SetCreatureOverrideAIScriptFinished();//Tell Determine Combat Round That I handled things. } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_preference_dcr //:: //:: Determine Combat Round for the Class Priority AI. //:: //:: Spell Queue AI's will cast spells form an ordered list attached to them. //:: To Attach a list, use the function ******, the conversation script ******, //:: or manually using these variables (must be done pre-spawn) *******. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/31/06 // DBR 2/28/06 - added support for mixing in the AI type preference (the type that prefers other AI types) // BMA 4/05/06 - bCheat || GetHasSpell() for SpellQueueResolve() // DBR 9/19/06 - swapped out distance checks for perception checks #include "nw_i0_generic" #include "x2_inc_switches" #include "ginc_param_const" #include "ginc_ai" #include "nw_i0_plot" //#include "ginc_debug" #include "ginc_ai" #include "ginc_group" int TankProtect(int nClassType); object CPGetSuitableEnemy(int nClassType); int SpellQueueResolve(); object SQGetSuitablePC(); object SQGetSuitableEnemy(); object SQGetSuitableFriend(); object AIPGetSuitableEnemy(int nAIType); void main() { /////This allows this custom DCR to re-call DetermineCombatRound() but with a new target (short circuiting the current) if (GetLocalInt(OBJECT_SELF,"X2_SPECIAL_COMBAT_AI_SCRIPT_OK"))//via a loophole, this function can be called recursively. { DeleteLocalInt(OBJECT_SELF,"X2_SPECIAL_COMBAT_AI_SCRIPT_OK"); return; //this makes sure redundant code is not run. } /////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////Handling Determine Combat round red tape object oIntruder = GetCreatureOverrideAIScriptTarget(); ClearCreatureOverrideAIScriptTarget(); //////this section ensures that AI's will fight even if they can't get to their preffered targets///////////// int nBlockCount=GetLocalInt(OBJECT_SELF,VAR_AP_BLOCKCOUNT); if (nBlockCount<0) //set creature to act normally { nBlockCount+=1; SetLocalInt(OBJECT_SELF,VAR_AP_BLOCKCOUNT,nBlockCount); return; } if (nBlockCount>10)//the AI has put the creature between a rock and a hard place. Act normally until this is all sorted out { //PrettyMessage("Overridding AI - " +GetTag(OBJECT_SELF) + " is stuck"); nBlockCount=-2; SetLocalInt(OBJECT_SELF,VAR_AP_BLOCKCOUNT,nBlockCount); return; } SetLocalInt(OBJECT_SELF,VAR_AP_BLOCKCOUNT,0); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // PrettyMessage("Entering DCR"); if (__InCombatRound()) //if I'm already doing stuff, don't overload me here. return; //Spell Queues occur before anything else if (SpellQueueResolve()) return; int nTotalPrefs=GetLocalInt(OBJECT_SELF,VAR_AP_NUM_PREF); int nChance=Random(100)+1; int i = 1; int nRange = GetLocalInt(OBJECT_SELF,VAR_AP_CHANCE_PREFIX+IntToString(i)); while ((nRangenTotalPrefs) return; //Random chance determined that standard DCR should handle this round //otherwise, we have our preferance int nPref = GetLocalInt(OBJECT_SELF,VAR_AP_PREF_PREFIX+IntToString(i)); if (nPref==ATTACK_PREFERENCE_STRONGEST) { // PrettyMessage("Which is Attack Strongest"); object oTemp,oHigh=OBJECT_INVALID;//find the strongest enemy near me int nHighest=0; int i=0, nTemp; //float fDist=0.0f; //while ((fDist<13.0f) && (GetIsObjectValid(oTemp=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE)))) while (GetIsObjectValid(oTemp=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN))) { //fDist=GetDistanceBetween(OBJECT_SELF,oTemp); nTemp=GetAbilityScore(oTemp,ABILITY_STRENGTH); if (nTemp>nHighest) { nHighest=nTemp; oHigh=oTemp; } } if (GetIsObjectValid(oHigh)) { SetCreatureOverrideAIScriptFinished();//Short circuit the Determine Combat round I'm already in, DetermineCombatRound(oHigh); //and Call myself again with the new target. ActionDoCommand(SetCreatureOverrideAIScriptFinished());// these two lines are appended to DCR()'s added actions.. ActionDoCommand(DetermineCombatRound());// that way if the actions cannot be completed, the creature does something SetCreatureOverrideAIScriptFinished(); //we handled things return; } // PrettyMessage("NO TARGET!!!"); return; } if (nPref==ATTACK_PREFERENCE_WEAKEST) { // PrettyMessage("Which is Attack Weakest"); object oTemp,oLow=OBJECT_INVALID;//find the weakest enemy near me int nLowest=1000; int i=0, nTemp; //float fDist=0.0f; //while ((fDist<13.0f) && (GetIsObjectValid(oTemp=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE)))) while (GetIsObjectValid(oTemp=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN))) { //fDist=GetDistanceBetween(OBJECT_SELF,oTemp); nTemp=GetAbilityScore(oTemp,ABILITY_STRENGTH); if (nTemp=0) oFriend=GetNearestCreature(CREATURE_TYPE_CLASS,nClassType,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); else oFriend=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,OBJECT_SELF,++i,CREATURE_TYPE_IS_ALIVE,TRUE); if (oFriend==OBJECT_INVALID) //no more candidates break; oThreat=GetLastAttacker(oFriend); if (!GetFactionEqual(OBJECT_SELF,oFriend)) //must be in my faction.. oFriend=OBJECT_INVALID; else if (!GetIsObjectValid(oThreat)) //attacker data must not be out of date oFriend=OBJECT_INVALID; else if (GetArea(oThreat)!=GetArea(OBJECT_SELF)) //must still be in the same area oFriend=OBJECT_INVALID; else if (GetAttackTarget(oThreat)!=oFriend) //must still be attacking my friend oFriend=OBJECT_INVALID; } if (GetIsObjectValid(oFriend)) { SetCreatureOverrideAIScriptFinished();//Short circuit the Determine Combat round I'm already in, DetermineCombatRound(oThreat); //and Call myself again with the new target. SetCreatureOverrideAIScriptFinished(); // return 1; } return 0; } object SQGetSuitablePC() { return GetNearestPC(); } object SQGetSuitableEnemy() { return GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); } object SQGetSuitableFriend() { return GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND); } int SpellQueueResolve() { int nWhichEntry=GetLocalInt(OBJECT_SELF,sSPELL_QUEUE_NUM_CAST)+1;//Which spell am I on? string sTarget = GetLocalString(OBJECT_SELF,sSPELL_QUEUE_TARGET_ENTRY+IntToString(nWhichEntry)); if (sTarget=="") //see if we are out of spells queued up { //SetCreatureOverrideAIScript(OBJECT_SELF,""); //turn off this special AI DeleteLocalInt(OBJECT_SELF,sSPELL_QUEUE_NUM_CAST); return 0; } SetLocalInt(OBJECT_SELF,sSPELL_QUEUE_NUM_CAST,nWhichEntry); int nSpell = GetLocalInt(OBJECT_SELF,sSPELL_QUEUE_ENTRY+IntToString(nWhichEntry)); int bCheat = GetLocalInt(OBJECT_SELF,sSPELL_QUEUE_ENTRY_CHEAT+IntToString(nWhichEntry)); int bInstant = GetLocalInt(OBJECT_SELF, sSPELL_QUEUE_ENTRY_INSTANTCAST+IntToString(nWhichEntry)); DeleteLocalInt(OBJECT_SELF,sSPELL_QUEUE_ENTRY+IntToString(nWhichEntry)); DeleteLocalString(OBJECT_SELF,sSPELL_QUEUE_TARGET_ENTRY+IntToString(nWhichEntry)); DeleteLocalInt(OBJECT_SELF,sSPELL_QUEUE_ENTRY_CHEAT+IntToString(nWhichEntry)); DeleteLocalInt(OBJECT_SELF,sSPELL_QUEUE_ENTRY_INSTANTCAST+IntToString(nWhichEntry)); object oTarget; if (GetStringLeft(sTarget,1)=="$") { if (sTarget=="$SELF") oTarget=OBJECT_SELF; else if (sTarget=="$PC") oTarget=SQGetSuitablePC(); else if (sTarget=="$ENEMY") oTarget=SQGetSuitableEnemy(); else if (sTarget=="$FRIEND") oTarget=SQGetSuitableFriend(); } else oTarget = GetTarget(sTarget); if (!GetIsObjectValid(oTarget)) return 0; // True if this is the last spell on the queue int bLastSpell = (GetLocalString(OBJECT_SELF,sSPELL_QUEUE_TARGET_ENTRY+IntToString(nWhichEntry+1)) == ""); if (bCheat || GetHasSpell(nSpell)) { //if an instant spell is last on the queue, we make it do the combat round override so that DCR doesn't clear the action queue. if(bInstant && !bLastSpell) { ActionCastSpellAtObject(nSpell,oTarget,METAMAGIC_ANY,bCheat, PROJECTILE_PATH_TYPE_DEFAULT, TRUE); //instant spells do not require a combat round, so we'll try to resolve the next spell in the queue, too, and we'll //do this until we either find a spell that isn't instant or we run out of spells, in which case we go to normal combat. SpellQueueResolve(); return 1; } __TurnCombatRoundOn(TRUE); //set me up not to be interrupted by other Determine Combat Rounds ActionCastSpellAtObject(nSpell,oTarget,METAMAGIC_ANY,bCheat, PROJECTILE_PATH_TYPE_DEFAULT, bInstant); __TurnCombatRoundOn(FALSE); SetCreatureOverrideAIScriptFinished();//Tell Determine Combat Round That I handled things. return 1; } return 0; } object CPGetSuitableEnemy(int nClassType) { float fDist, fDistmin; if (nClassType==AI_CLASS_TYPE_MELEE) //currently encompasses Barbarians, Clerics, Fighters, Monks and Paladins { object oChoice=GetNearestCreature(CREATURE_TYPE_CLASS,CLASS_TYPE_BARBARIAN,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_IS_ALIVE,TRUE); fDistmin=GetDistanceBetween(OBJECT_SELF,oChoice); if (fDistmin==0.0f) fDistmin=1000.0f; object oNext=GetNearestCreature(CREATURE_TYPE_CLASS,CLASS_TYPE_CLERIC,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_IS_ALIVE,TRUE); if ((fDist = GetDistanceBetween(OBJECT_SELF,oNext))!=0.0f) //if valid if (fDistfThresh) { ClearAllActions(TRUE); __TurnCombatRoundOn(TRUE); ActionMoveToObject(oGuardee,TRUE,fThresh/3.0f); __TurnCombatRoundOn(FALSE); } } else { fThresh=GetLocalFloat(OBJECT_SELF,VAR_P_PROXIMITY); if (fDist>fThresh) { ClearAllActions(); if (fDist>GetLocalFloat(OBJECT_SELF,VAR_P_PROXIMITY_RUN)) ActionMoveToObject(oGuardee,TRUE,fThresh/3.0f); else ActionMoveToObject(oGuardee,FALSE,fThresh/3.0f); } if (GetIsInCombat(oGuardee)) //they're in trouble, but I'm not.. better fight. DetermineCombatRound(); } AIContinueInterruptedScript(CREATURE_SCRIPT_ON_HEARTBEAT); //this script is an interrupt script, so this must be called //when you want the original to play } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_aipref //:: //:: I prefer to attack creatures with certain AI's over other creatures. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/28/06 #include "ginc_ai" void main() { //Call the AIAttackPreference command first. AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_AI_TYPE); //Then put as many of these in whatever order you want. AIAttackTypeInOrder(OBJECT_SELF, AI_TYPE_PROTECTOR ); //first AI to attack.. AIAttackTypeInOrder(OBJECT_SELF, AI_TYPE_RUNNING_ALARM ); //second.. //----*NOTES*----- //Acceptable parameters: // AI_TYPE_RUNNING_ALARM // AI_TYPE_COWARD // AI_TYPE_PROTECTOR // AI_TYPE_TANK // AI_TYPE_COUNTER_CASTER // AI_TYPE_SPELL_QUEUE // AI_TYPE_GROUP_ATTACK } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_classpriority //:: //:: Has a creature prefer to attack weaker characters of the ones that are nearby. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { //Uses the AIAttackPreference command. An optional third integer parameter will set the probability (out of 100) //that this AI type is used in a round of combat. Default == 100. AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_STRONGEST ); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_attackweakest //:: //:: Has a creature attack the weakest character nearby. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { //Uses the AIAttackPreference command. An optional third integer parameter will set the probability (out of 100) //that this AI type is used in a round of combat. Default == 100. AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_WEAKEST ); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_classpriority //:: //:: Used to Tell a creature to fight certain classes before others. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { //Uses the AIAttackPreference command. An optional third integer parameter can set the probability (out of 100) //that this AI type is used in a round of combat. Default == 100. AIAttackPreference(OBJECT_SELF, ATTACK_PREFERENCE_CLASS_PRIORITY); //Just change this! That's it! Wo-ah -oh -oh, it's MAGIC! You knooooooowww- AIAttackInOrder(OBJECT_SELF, CLASS_TYPE_WIZARD ); //first class to attack.. AIAttackInOrder(OBJECT_SELF, CLASS_TYPE_SORCERER ); //second.. AIAttackInOrder(OBJECT_SELF, AI_CLASS_TYPE_MELEE ); //so on.. AIAttackInOrder(OBJECT_SELF, CLASS_TYPE_BARD ); //----*NOTES*----- //Any number of classes can be provided. //The second parameter is from the CLASS_TYPE_* constant list. //There are custom constants (second paramter) that you can provide to prefer a range of classes. Those are: //AI_CLASS_TYPE_MELLE - melee users //AI_CLASS_TYPE_RANGED - ranged users //AI_CLASS_TYPE_SPELLCASTERS - magic users } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_counterspell //:: //:: A loveable, portable anti-mage. Full of counterspells and debuff's //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { //Set either of these two flags to get preferred behavior. int bCounterSpell =1; int bDispel = 1; AIMakeCounterCaster(OBJECT_SELF, bCounterSpell, bDispel); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_coward //:: //:: I am a frightened, frightened little boy. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" #include "x0_i0_anims" void main() { //No customization needed. Creature will flee from all combat. SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_damageswitch //:: //:: SpawnScript that will alter a creature's behavior based on how hurt they are. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/28/06 #include "ginc_ai" #include "x0_i0_combat" void main() { int nHealthPercent=GetHealthPercent(OBJECT_SELF); if (nHealthPercent>=70) //at 70%-100%, do nothing { //DelayCommand(0.2f,SpeakString("You will never defeat me!")); //AIResetType(OBJECT_SELF); //for clean AI transition, call AIResetType before setting a new AI type. //AIIgnoreCombat(OBJECT_SELF); } else if (nHealthPercent>=30) //at 30%-69%, attack weakest { //DelayCommand(0.2f,SpeakString("You're stronger than I thought!!")); //AIResetType(OBJECT_SELF); //AIAttackPreference(OBJECT_SELF,ATTACK_PREFERENCE_WEAKEST); } else //from 29% and below, run like the dickens { //DelayCommand(0.2f,SpeakString("Oh God, Not in the Face!!")); //AIResetType(OBJECT_SELF); //SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); } //This line is the only REQUIRED statement for this AI type. AIDamageSwitchEndStatement(); //unless you're sure what will happen, don't remove this please. } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_defensivetank //:: //:: Try my best to take the brunt of the damage for friendlies. Also, healing, evade, parry. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 #include "ginc_ai" void main() { //These are so simple to use! Amazing! AIMakeTank(OBJECT_SELF); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_donothing //:: //:: Do nothing during combat. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/28/06 #include "ginc_ai" void main() { SetCombatOverrides(OBJECT_SELF,OBJECT_INVALID,-1,-1,OVERRIDE_ATTACK_RESULT_DEFAULT,-1,-1,FALSE,TRUE,FALSE,FALSE); AIAssignDCR(OBJECT_SELF,"gai_ignore_dcr"); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gai_template_fightnrun //:: //:: Attack! When I'm low on health, Run away! If close to death, Attack again! //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 2/28/06 #include "ginc_ai" #include "x0_i0_combat" void main() { int nHealthPercent=GetHealthPercent(OBJECT_SELF); int nLastSection = GetLocalInt(OBJECT_SELF,"DS-LS"); if (nHealthPercent>30) //Standard DCR Attack if 30% or higher { if (nLastSection==1) return; SetLocalInt(OBJECT_SELF,"DS-LS",1); AIResetType(OBJECT_SELF); SetCombatCondition(X0_COMBAT_FLAG_COWARDLY,FALSE); } else if (nHealthPercent>10) //from 15%-29%, run like the dickens { if (nLastSection==2) return; SetLocalInt(OBJECT_SELF,"DS-LS",2); AIResetType(OBJECT_SELF); SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); } else { if (nLastSection==3) return; SetLocalInt(OBJECT_SELF,"DS-LS",3); AIResetType(OBJECT_SELF); SetCombatCondition(X0_COMBAT_FLAG_COWARDLY,FALSE); AITurnOffDamageSwitch(); } AIDamageSwitchEndStatement(); //unless you're sure what will happen, don't remove this please. } Global Being (Creature) // gb_comp_attack.nss /* Companion OnAttacked handler Based off Associate OnAttacked (NW_CH_AC5) */ // ChazM 12/5/05 // BMA-OEI 7/08/06 -- Rewrote to preserve action queue // BMA-OEI 7/14/06 -- Follow mode interruptible // BMA-OEI 7/17/06 -- Removed STAND_GROUND check, added spell target enemy check // BMA-OEI 9/12/06 -- Added STAND_GROUND check back #include "X0_INC_HENAI" void main() { SpeakString( "NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK ); if ( ( GetAssociateState(NW_ASC_IS_BUSY) == FALSE ) && ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) ) { if ( ( GetNumActions(OBJECT_SELF) == 0 ) || ( GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOW ) ) { // If I don't already have a valid target... if ( ( GetIsObjectValid(GetAttackTarget()) == FALSE ) && ( ( GetIsObjectValid(GetAttemptedSpellTarget()) == FALSE ) || ( GetIsEnemy(GetAttemptedSpellTarget()) == FALSE ) ) ) { object oAttacker = GetLastAttacker(); if ( GetIsObjectValid(oAttacker) == TRUE ) { HenchmenCombatRound( oAttacker ); } } } } if ( GetSpawnInCondition(NW_FLAG_ATTACK_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_ATTACKED) ); } } // gb_comp_block /* companion On Block */ // ChazM 12/5/05 //::////////////////////////////////////////////////// //:: X0_CH_HEN_BLOCK /* OnBlocked handler for henchmen/associates. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 01/06/2003 //::////////////////////////////////////////////////// void main() { object oDoor = GetBlockingDoor(); int nInt = GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE); int nStr = GetAbilityScore(OBJECT_SELF, ABILITY_STRENGTH); if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && nInt >= 3) { DoDoorAction(oDoor, DOOR_ACTION_OPEN); } else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH) && nStr >= 16) { DoDoorAction(oDoor, DOOR_ACTION_BASH); } } // gb_comp_combat.nss /* Companion OnEndCombatRound handler Based off Associate End of Combat End (NW_CH_AC3) */ // ChazM 12/5/05 // BMA-OEI 7/08/06 // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // BMA_OEI 09/13/06 -- Added NW_ASC_MODE_STAND_GROUND check #include "x0_inc_henai" void main() { if ( ( GetSpawnInCondition(NW_FLAG_SET_WARNINGS) == FALSE ) && ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) ) { if (GetAssociateState(NW_ASC_MODE_PUPPET)==FALSE) //DBR 8/03/06 If I am a puppet. I put nothing on the ActionQueue myself. HenchmenCombatRound( OBJECT_INVALID ); } if ( GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_END_COMBAT_ROUND) ); } } // gb_comp_conv.nss /* Companion OnConversation handler Based on henchmen/associate OnDialogue handler (X0_CH_HEN_CONV) */ // ChazM 12/5/05 // ChazM 5/18/05 reference to master now uses GetCurrentMaster() - returns master for associate or companion // BMA-OEI 7/14/06 -- Update to use CompanionRespondToShout(), follow mode interruptible // BMA-OEI 7/17/06 -- Check if oShouter is valid, and OBJECT_SELF is AbleToTalk(), respond to master and friends // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // ChazM 8/30/06 FightIfYouAintBusy() clears actions if following; Don't respond to companion shouts if in puppet mode. // ChazM 9/13/06 Added some debug (to help determine why PC doesn't always listen to commands). #include "x0_inc_henai" #include "x0_i0_henchman" #include "ginc_companion" //* GeorgZ - Put in a fix for henchmen talking even if they are petrified int AbleToTalk( object oSelf ); // Companion reaction to shouts void CompanionRespondToShout( object oShouter, int nShoutIndex, object oIntruder=OBJECT_INVALID ); // CompanionRespondToShout() helper void FightIfYouAintBusy( object oTarget ); void main() { //int i = GetLocalInt( OBJECT_SELF, sAssociateMasterConditionVarname ); //PrettyDebug( "gb_comp_conv: " + GetName(OBJECT_SELF) + " - Associate State: " + IntToHexString(i) ); //PrettyDebug( "gb_comp_conv: " + GetName(OBJECT_SELF) + " - Speaker: " + GetName(GetLastSpeaker()) + " - Heard Pattern: " + IntToString(GetListenPatternNumber()) ); if ( ( GetIsHenchmanDying(OBJECT_SELF) == FALSE ) && ( GetIsDead(OBJECT_SELF) == FALSE ) ) { object oShouter = GetLastSpeaker(); int nMatch = GetListenPatternNumber(); // BMA-OEI 7/17/06 -- Min. conditions to continue if ( ( GetIsObjectValid(oShouter) == TRUE ) && ( AbleToTalk(OBJECT_SELF) == TRUE ) ) { if ( nMatch == -1 ) { // * September 2 2003 // * Added the GetIsCommandable check back in so that // * Henchman cannot be interrupted when they are walking away if ( ( GetCommandable(OBJECT_SELF) == TRUE ) && ( GetCurrentAction() != ACTION_OPENLOCK ) ) { //SetCommandable( TRUE ); ClearActions( CLEAR_X0_CH_HEN_CONV_26 ); //string sDialogFileToUse = GetDialogFileToUse( oShouter ); BeginConversation( "", oShouter ); } } else { object oMaster = GetCurrentMaster(); //GetPCLeader( OBJECT_SELF ); object oIntruder = OBJECT_INVALID; //string sOut = GetName(OBJECT_SELF) + " - I heard shout: " + IntToString(nMatch) + " from: " + GetName(oShouter); // Speaker is our master if ( ( GetIsObjectValid(oMaster) == TRUE ) && ( oMaster == oShouter ) ) { //sOut += " who is my master."; SetCommandable( TRUE ); bkRespondToHenchmenShout( oShouter, nMatch, oIntruder ); // x0_inc_henai } // Speaker is our friend else if ( ( GetFactionEqual(oShouter) == TRUE ) || ( GetIsFriend(oShouter) == TRUE ) ) { //sOut += " who is my friend."; if ( nMatch == 4 ) // ? { oIntruder = GetLocalObject( oShouter, "NW_BLOCKER_INTRUDER" ); } else if ( nMatch == 5 ) // ? { oIntruder = GetLastHostileActor( oShouter ); } //SetCommandable( TRUE ); CompanionRespondToShout( oShouter, nMatch, oIntruder ); } /*else { sOut += " who is nothing to me."; }*/ //PrettyDebug(sOut); } } } if( GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_DIALOGUE) ); } } //* GeorgZ - Put in a fix for henchmen talking even if they are petrified int AbleToTalk( object oSelf ) { if ( GetHasEffect( EFFECT_TYPE_CONFUSED, oSelf ) || GetHasEffect( EFFECT_TYPE_DOMINATED, oSelf ) || GetHasEffect( EFFECT_TYPE_FRIGHTENED, oSelf ) || GetHasEffect( EFFECT_TYPE_PARALYZE, oSelf ) || GetHasEffect( EFFECT_TYPE_PETRIFY, oSelf ) || GetHasEffect( EFFECT_TYPE_STUNNED, oSelf ) ) { return ( FALSE ); } return ( TRUE ); } // Companion reaction to shouts void CompanionRespondToShout( object oShouter, int nShoutIndex, object oIntruder=OBJECT_INVALID ) { //If I am a puppet. I put nothing on the ActionQueue myself. if (GetAssociateState(NW_ASC_MODE_PUPPET)) return; int bSurrendered = GetLocalInt( OBJECT_SELF, "Generic_Surrender" ); if ( bSurrendered ) return; switch ( nShoutIndex ) { case 1: // NW_GENERIC_SHOUT_I_WAS_ATTACKED case 2: // NW_GENERIC_SHOUT_MOB_ATTACK case 3: // NW_GENERIC_SHOUT_I_AM_DEAD case 6: // CALL_TO_ARMS FightIfYouAintBusy( GetLastHostileActor(oShouter) ); break; //For this shout to work the object must shout the following //string sHelp = "NW_BLOCKER_BLK_" + GetTag(OBJECT_SELF); case 4: // BLOCKER OBJECT HAS BEEN DISTURBED FightIfYouAintBusy( oIntruder ); break; case 5: // ATTACK MY TARGET AdjustReputation( oIntruder, OBJECT_SELF, -100 ); SetIsTemporaryEnemy( oIntruder ); FightIfYouAintBusy( oIntruder ); break; default: } } // CompanionRespondToShout() helper void FightIfYouAintBusy( object oTarget ) { // Ignore if you've been told to stand ground, already busy or already doing something, or following somebody if ( ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) && ( GetAssociateState(NW_ASC_IS_BUSY) == FALSE ) && //( GetIsInCombat(OBJECT_SELF) == FALSE ) && ( ( GetNumActions(OBJECT_SELF) == 0 ) || ( GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOW ) ) ) { if (GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOW ) ClearAllActions(); HenchmenCombatRound( oTarget ); } } // gb_comp_damage.nss /* Companion OnDamaged handler Based off Associate OnDamaged (NW_CH_AC6) */ // ChazM 12/5/05 // ChazM 5/18/05 reference to master now uses GetCurrentMaster() - returns master for associate or companion // BMA-OEI 7/08/06 -- Rewrote to preserve action queue // BMA-OEI 7/14/06 -- Follow mode interruptible // BMA-OEI 7/17/06 -- Removed STAND_GROUND check, added spell target checks // BMA-OEI 9/13/06 -- Added STAND_GROUND check back #include "X0_INC_HENAI" void main() { if ( ( GetAssociateState(NW_ASC_IS_BUSY) == FALSE ) && ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) ) { if ( ( GetNumActions(OBJECT_SELF) == 0 ) || ( GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOW ) ) { object oDamager = GetLastDamager(); object oTarget = GetAttackTarget(); if ( GetIsObjectValid(oTarget) == FALSE ) { oTarget = GetAttemptedSpellTarget(); } if ( ( GetIsObjectValid(oTarget) == FALSE ) || ( GetIsEnemy(oTarget) == FALSE ) || ( GetIsDamagerABetterTarget(oDamager, oTarget) == TRUE ) ) { oTarget = oDamager; } if ( GetIsObjectValid(oTarget) == TRUE ) { HenchmenCombatRound( oTarget ); } } } if ( GetSpawnInCondition(NW_FLAG_DAMAGED_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_DAMAGED) ); } } // gb_comp_death /* OnDeath handler to queue KnockOut script for companions */ // ChazM 8/17/05 // BMA-OEI 12/19/05 knock out death system // BMA-OEI 1/26/06 exit if owned and controlled // BMA-OEI 2/27/06 DeathScript support, exit if not in PC faction // BMA-OEI 2/28/06 #include "ginc_companion" #include "ginc_death" #include "ginc_debug" void main() { object oDead = OBJECT_SELF; PrintString( "gb_comp_death: " + GetName(oDead) + " executing OnDeath event" ); // Abort if dying character is owned PC (owned PCs should fire module OnDeath) if ( GetIsOwnedByPlayer( oDead ) == TRUE ) { PrintString( "** gb_comp_death: " + GetName(oDead) + " is owned by a player. ABORT!" ); return; } // Check for additional death script string sDeathScript = GetLocalString( oDead, "DeathScript" ); if ( sDeathScript != "" ) ExecuteScript( sDeathScript, oDead ); // Abort if dying character is not in PC faction if ( GetIsObjectInParty( oDead ) == FALSE ) { PrintString( "** gb_comp_death: " + GetName(oDead) + " not in " + GetName(GetFirstPC()) + "'s party. ABORT!" ); return; } // Queue knockout script AssignCommand( oDead, KnockOutCreature( oDead ) ); } // gb_comp_distrb /* companion On Disturbed */ // ChazM 12/5/05 // ChazM 5/17/06 - comment changes //:://///////////////////////////////////////////// //:: Henchmen: On Disturbed //:: NW_C2_AC8 //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* Determine Combat Round on disturbed. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Oct 16, 2001 //:://///////////////////////////////////////// // * Make me hostile the faction of my last attacker (TEMP) // AdjustReputation(OBJECT_SELF,GetFaction(GetLastAttacker()),-100); // * Determined Combat Round #include "X0_INC_HENAI" void main() { object oTarget = GetLastDisturbed(); if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget())) { if(GetIsObjectValid(oTarget)) { HenchmenCombatRound(oTarget); } else { } } if(GetSpawnInCondition(NW_FLAG_DISTURBED_EVENT)) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DISTURBED)); } } // gb_comp_heart /* companion heartbeat */ // ChazM 12/5/05 // BMA-OEI 2/6/06 cleaned up comments, preserve action queue // BMA-OEI 2/8/06 removed debug // BMA-OEI 2/23/06 added 0.5f minimal follow distance // ChazM 2/23/06 added commented PrettyDebugs. // BMA-OEI 2/28/06 increase min follow distance = 2.0f // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // ChazM 8/18/06 added debug calls. //::////////////////////////////////////////////////// //:: X0_CH_HEN_HEART /* OnHeartbeat event handler for henchmen/associates. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 01/05/2003 //::////////////////////////////////////////////////// #include "X0_INC_HENAI" #include "X2_INC_SUMMSCALE" #include "X2_INC_SPELLHOOK" #include "ginc_misc" #include "ginc_companion" #include "ginc_debug" //#include "ginc_death" const float MIN_FOLLOW_DISTANCE = 2.0f; void OriginalHenchHB(); void DoDebug(string sMessage) { return; string sMyName = GetName(OBJECT_SELF); PrettyDebug("gb_comp_heart: " + sMyName + " - " + sMessage); } void main() { //string sMyName = GetName(OBJECT_SELF); //PrettyDebug("gb_comp_heart: " + sMyName + "'s heartbeat"); //PrettyDebug("GetFollowDistance: " + FloatToString(GetFollowDistance())); //PrettyDebug("GetLocalInt('NW_ASSOCIATE_MASTER'): " + IntToString(GetLocalInt(OBJECT_SELF, "NW_ASSOCIATE_MASTER"))); int bDying = (GetIsDead(OBJECT_SELF) || GetIsHenchmanDying(OBJECT_SELF)); /* // If the henchman is in dying mode, make sure // they are non commandable. Sometimes they seem to // 'slip' out of this mode if (bDying == TRUE) { int bCommandable = GetCommandable(); if (bCommandable == TRUE) { ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 65.0); SetCommandable(FALSE); } return; } */ // If we're dying or busy, we return // (without sending the user-defined event) // file: nw_i0_generic, x0_i0_henchmen, assoc, x0_i0_states, henai int bBusy = GetAssociateState(NW_ASC_IS_BUSY); if ((bDying == TRUE) || (bBusy == TRUE)) { return; } int bInCombat = GetIsInCombat(); if (bInCombat == FALSE) { // Check to see if should re-enter stealth mode int nStealth=GetLocalInt(OBJECT_SELF, "X2_HENCH_STEALTH_MODE"); // x2_inc_henai.nss if((nStealth == 1) || (nStealth == 2)) { if (GetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH) == FALSE) { SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, TRUE); } } // * checks to see if a ranged weapon was being used // * if so, it equips it back object oRight = GetLocalObject(OBJECT_SELF, "X0_L_RIGHTHAND"); // x0_i0_equip.nss if (GetIsObjectValid(oRight) == TRUE) { SetLocalObject(OBJECT_SELF, "X0_L_RIGHTHAND", OBJECT_INVALID); if (GetWeaponRanged(oRight) == TRUE) { ClearAllActions(); bkEquipRanged(OBJECT_INVALID, TRUE, TRUE); return; } } } OriginalHenchHB(); } void OriginalHenchHB() { // GZ: Fallback for timing issue sometimes preventing epic summoned creatures from leveling up to their master's level. // There is a timing issue with the GetMaster() function not returning the fof a creature // immediately after spawn. Some code which might appear to make no sense has been added // to the nw_ch_ac1 and x2_inc_summon files to work around this // This code is only run at the first hearbeat int nLevel = SSMGetSummonFailedLevelUp(OBJECT_SELF); // x2_inc_summscale.nss if (nLevel != 0) { int nRet; if (nLevel == -1) // special shadowlord treatment { SSMScaleEpicShadowLord(OBJECT_SELF); } else if (nLevel == -2) { SSMScaleEpicFiendishServant(OBJECT_SELF); } else { nRet = SSMLevelUpCreature(OBJECT_SELF, nLevel, CLASS_TYPE_INVALID); if (nRet == FALSE) { WriteTimestampedLogEntry("WARNING - nw_ch_ac1:: could not level up " + GetTag(OBJECT_SELF) + "!"); } } // regardless if the actual levelup worked, we give up here, because we do not // want to run through this script more than once. SSMSetSummonLevelUpOK(OBJECT_SELF); } // Check if concentration is required to maintain this creature X2DoBreakConcentrationCheck(); // x2_inc_spellhook.nss object oMaster = GetCurrentMaster(); // GetPCLeader(OBJECT_SELF); // ginc_companions.nss int bBusy = GetAssociateState(NW_ASC_IS_BUSY); if (bBusy == FALSE) { DoDebug("Not busy"); // Seek out and disable undisabled traps object oTrap = GetNearestTrapToObject(); if (GetAssociateState(NW_ASC_MODE_PUPPET)==FALSE) //DBR 8/03/06 If I am a puppet. I put nothing on the ActionQueue myself. if (bkAttemptToDisarmTrap(oTrap) == TRUE) return ; // x0_inc_henai.nss if (GetIsObjectValid(oMaster) == TRUE) { DoDebug("Have valid master"); // BMA-OEI 6/20/06 if ( GetNumActions( OBJECT_SELF ) == 0 ) //if (GetCurrentAction(OBJECT_SELF) == ACTION_INVALID) // GetNumActions? { DoDebug("No actions on queue"); if (GetIsInCombat(OBJECT_SELF) == FALSE) // GetIsFighting? { DoDebug("Not in combat"); if (GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE) { DoDebug("Not standing ground"); if (GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH) == TRUE) { DoDebug("Throwing a Search action"); ActionUseSkill(SKILL_SEARCH, OBJECT_SELF); } float fFollowDistance = GetFollowDistance(); if (fFollowDistance < MIN_FOLLOW_DISTANCE) { fFollowDistance = MIN_FOLLOW_DISTANCE; // AFFO() doesn't do anything if fd < 0.5 } if(GetDistanceToObject(oMaster) > fFollowDistance) { DoDebug("Throwing an ActionForceFollow"); ActionForceFollowObject(oMaster, fFollowDistance); } } } } } // * if I am dominated, ask for some help if ((GetHasEffect(EFFECT_TYPE_DOMINATED, OBJECT_SELF) == TRUE) && (GetIsEncounterCreature(OBJECT_SELF) == FALSE)) { SendForHelp(); // x0_inc_henai.nss } if (GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)) { SignalEvent(OBJECT_SELF, EventUserDefined(1001)); } } } // gb_comp_percep.nss /* Companion OnPerception handler Based off Associate OnDamaged (X0_CH_HEN_PERCEP) */ // ChazM 12/5/05 // ChazM 5/18/05 reference to master now uses GetCurrentMaster() - returns master for associate or companion // ChazM 7/11/06 added exception for force follow. // BMA-OEI 7/14/06 -- Rewrote to preserve action queue, follow mode interruptible // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // DBR - 09/08/06 - fix for companions training down a line of hostiles - added GetCurrentAction/GetNumActions check // DBR - 09/13/06 - Removed specific target for HenchmanCombatRound() when a hostile is seen // DBR - 10/25/06 - Added checks for Defend Master new behavior - companions do not attack those that are not in combat. #include "X0_INC_HENAI" #include "ginc_companion" void OriginalHenchPercep(); void main() { // 5/2/06 BDF: The segment below checks to see if the owner is in the process of casting a spell (i.e. True Name!) // or has any other actions queued. If so, let's escape so that the OriginalHenchPercep() cannot inadvertantly // interrupt or clear any actions that the player may have queued up while they were in possession of this creature. // Ok to interrupt if we are just following. //if (GetNumActions(OBJECT_SELF) == 0) OriginalHenchPercep(); } void OriginalHenchPercep() { //This is the equivalent of a force conversation bubble, should only be used if you want an NPC //to say something while he is already engaged in combat. if (GetAssociateState(NW_ASC_MODE_PUPPET)==FALSE) //DBR 8/03/06 If I am a puppet. I put nothing on the ActionQueue myself. { if( GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION) == TRUE ) { ActionStartConversation( OBJECT_SELF ); } if ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) { if ( GetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH) == FALSE ) { // Ignore if I already have a valid target if ( ( GetIsObjectValid(GetAttemptedAttackTarget()) == FALSE ) && ( GetIsObjectValid(GetAttemptedSpellTarget()) == FALSE ) ) { if ( GetLastPerceptionSeen() == TRUE ) { object oSeen = GetLastPerceived(); if ( GetIsEnemy(oSeen) == TRUE ) { if ( (GetNumActions(OBJECT_SELF)<=0) || //HencmenCR isn't like DCR - we only want to call it to start attacking a new target ((GetCurrentAction(OBJECT_SELF)==ACTION_FOLLOW))) { // SetFacingPoint( GetPosition(oSeen) ); // DBR 10/25/06 - new behavior, we do not wish 'defending' companions to fight those that are not in combat. if (!GetAssociateState(NW_ASC_MODE_DEFEND_MASTER) || (GetIsInCombat(oSeen))) HenchmenCombatRound( ); } else { // DBR 10/25/06 - new behavior, we do not wish 'defending' companions to fight those that are not in combat. if (!GetAssociateState(NW_ASC_MODE_DEFEND_MASTER) || (GetIsInCombat(oSeen))) ActionDoCommand(HenchmenCombatRound()); //if perception ignored, check for hostiles when I am done with my actions. (must be no target specified) } } else if ( ( GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) == TRUE ) && ( GetIsPC(oSeen) == TRUE ) ) { ActionStartConversation( OBJECT_SELF ); } } } } } } if ( GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_PERCEIVE) ); } } // gb_comp_rest /* companion On Rest */ // ChazM 12/5/05 #include "ginc_debug" void main() { object oPC = GetLastPCRested(); int nType = GetLastRestEventType(); //PrettyMessage("gb_comp_rest: rest event fired for " + GetName(oPC) + " type " + IntToString(nType)); } // gb_comp_spawn /* companion On Spawn */ // ChazM 12/5/05 // BMA-OEI 12/19/05 spawn as killable companions // ChazM 6/15/06 - default follow distance changed back to 2 meters // ChazM 8/3/06 - Companions default to defend master mode // ChazM 8/21/06 - removed kinc_globals include // ChazM 8/24/06 - changed check for setting associate state. // ChazM 8/24/06 - changed default for open locks and disarm traps to off // ChazM 9/8/06 - chaged casting default to SCALED_CASTING // ChazM 9/18/06 - If I have any levels in rogue then default to opening locks and finding traps // BMA-OEI 10/19/06 - Roster members default N2_COMBAT_MODE_USE_DISABLED #include "x0_inc_henai" #include "x2_inc_banter" #include "ginc_companion" // * Scan through all equipped items and make // * sure they are identified void IdentifyEquippedItems(object oCreature=OBJECT_SELF) { int i = 0; object oItem; for (i = 0; i< NUM_INVENTORY_SLOTS; i++) { oItem = GetItemInSlot(i, oCreature); if (GetIsObjectValid(oItem) == TRUE) SetIdentified( oItem, TRUE); } } void main() { string sAreaTag = GetTag(GetArea(OBJECT_SELF)); string sModuleTag = GetTag(GetModule()); string sMyTag = GetTag(OBJECT_SELF); // Sets up the special henchmen listening patterns (gb_setassociatelistenpatterns) SetAssociateListenPatterns(); // Set standard combat listening patterns (x0_i0_spawncond) SetListeningPatterns(); // Set additional henchman listening patterns (x0_inc_henai) bkSetListeningPatterns(); // Default behavior for henchmen at start SetAssociateState(NW_ASC_SCALED_CASTING); SetAssociateState(NW_ASC_HEAL_AT_50); if (GetLevelByClass(CLASS_TYPE_ROGUE) > 0) { SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS); SetAssociateState(NW_ASC_DISARM_TRAPS); } // * July 2003. Set this to true so henchmen // * will hopefully run off a little less often // * by default // * September 2003. Bad decision. Reverted back // * to original. This mode too often looks like a bug // * because they hang back and don't help each other out. // // companions defaulted to defend master - hoping not a repeat // of previous bad desicion... //if (GetAssociateType(OBJECT_SELF) == ASSOCIATE_TYPE_NONE) // won't work - henchmen won't be set yet as associates //if (GetCompanionNumberByTag(GetTag(OBJECT_SELF)) > 0) // don't want dependency on kinc_companion if (GetIsRosterMember(OBJECT_SELF)) { SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, TRUE); // BMA-OEI 10/19/06 - Disable combat mode switching during combat SetLocalInt(OBJECT_SELF, N2_COMBAT_MODE_USE_DISABLED, TRUE); } SetAssociateState(NW_ASC_DISTANCE_2_METERS); // Use melee weapons by default SetAssociateState(NW_ASC_USE_RANGED_WEAPON, FALSE); // Set starting location SetAssociateStartLocation(); // Set respawn location SetRespawnLocation(); // For some general behavior while we don't have a master, // let's do some immobile animations SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); // * September 2003 IdentifyEquippedItems(); // Companion corpses do not decay SetIsDestroyable( FALSE, TRUE, TRUE ); } // gb_comp_spell.nss /* Companion OnSpellCastAt handler Based off Henchmen On Spell Cast At (NW_CH_ACB) */ // ChazM 12/5/05 // ChazM 5/18/05 don't react if spell cast by someone else in the same party. reference to master now uses GetCurrentMaster() - returns master for associate or companion // BMA-OEI 7/08/06 -- Rewrote to preserve action queue // BMA-OEI 7/14/06 -- Follow mode interruptible // BMA-OEI 7/17/06 -- Removed STAND_GROUND check // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // BMA-OEI 09/20/06 -- AOEBEHAVIOR: Disable spell casting while Polymorphed, Removed ActionForceMove #include "x0_i0_henchman" #include "X0_INC_HENAI" #include "x2_i0_spells" #include "ginc_companion" void OriginalHenchSpell(); void main() { // BMA-OEI 7/08/06 -- Is this necessary for companion AI? (No respawn rules) if ( GetIsHenchmanDying() == TRUE ) { int nSpellID = GetLastSpell(); if ( ( nSpellID == SPELL_CURE_LIGHT_WOUNDS ) || ( nSpellID == SPELL_CURE_MINOR_WOUNDS ) || ( nSpellID == SPELL_CURE_MODERATE_WOUNDS ) || ( nSpellID == SPELL_CURE_CRITICAL_WOUNDS ) || ( nSpellID == SPELL_CURE_SERIOUS_WOUNDS ) || ( nSpellID == SPELL_HEAL ) || ( nSpellID == 506 ) || // * Healing Kits ( nSpellID == SPELLABILITY_LAY_ON_HANDS ) || ( nSpellID == 309 ) || // * Wholeness of Body ( nSpellID == SPELL_MASS_CURE_LIGHT_WOUNDS ) || // JLR - OEI 08/23/05 -- Renamed for 3.5 ( nSpellID == SPELL_RAISE_DEAD ) || ( nSpellID == SPELL_RESURRECTION ) || ( nSpellID == SPELL_MASS_HEAL ) || ( nSpellID == SPELL_GREATER_RESTORATION ) || ( nSpellID == SPELL_REGENERATE ) || ( nSpellID == SPELL_AID ) || ( nSpellID == SPELL_VIRTUE ) ) { SetLocalInt( OBJECT_SELF, "X0_L_WAS_HEALED", 10 ); WrapCommandable( TRUE, OBJECT_SELF ); DoRespawn( GetLastSpellCaster(), OBJECT_SELF ); // userdef? return; } } OriginalHenchSpell(); } void OriginalHenchSpell() { object oCaster = GetLastSpellCaster(); if ( GetLastSpellHarmful() == TRUE ) { SpeakString( "NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK ); // * GZ Oct 3, 2003 // * Really, the engine should handle this, but hey, this world is not perfect... // * If I was hurt by my master or the creature hurting me has // * the same master // * Then clear any hostile feelings I have against them // * After all, we're all just trying to do our job here // * if we singe some eyebrow hair, oh well. if ( GetFactionEqual(oCaster, OBJECT_SELF) == TRUE ) { ClearPersonalReputation( oCaster, OBJECT_SELF ); if ( GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT) ); } return; } int bAttack = TRUE; int nSpellID = GetLastSpell(); // * AOE Behavior // BMA-OEI 7/08/06 -- Likely to lose action queue in this block if ( MatchAreaOfEffectSpell(nSpellID) == TRUE ) // ? { if ( GetIsHenchmanDying() == FALSE ) { if (GetAssociateState(NW_ASC_MODE_PUPPET)==FALSE) //DBR 8/03/06 If I am a puppet. I put nothing on the ActionQueue myself. { SetCommandable( TRUE ); //* GZ 2003-Oct-02 : New AoE Behavior AI int nBehavior = GetBestAOEBehavior( nSpellID ); switch ( nBehavior ) { case X2_SPELL_AOEBEHAVIOR_DISPEL_L: case X2_SPELL_AOEBEHAVIOR_DISPEL_N: case X2_SPELL_AOEBEHAVIOR_DISPEL_M: case X2_SPELL_AOEBEHAVIOR_DISPEL_G: case X2_SPELL_AOEBEHAVIOR_DISPEL_C: // BMA-OEI 9/20/06: Disable spell casting while Polymorphed if ( GetHasEffect( EFFECT_TYPE_POLYMORPH ) == FALSE ) { bAttack = FALSE; ActionCastSpellAtLocation( nBehavior, GetLocation(OBJECT_SELF) ); } //ActionDoCommand( SetCommandable(TRUE) ); //SetCommandable( FALSE ); break; case X2_SPELL_AOEBEHAVIOR_FLEE: if ( GetCurrentAction() != ACTION_MOVETOPOINT ) { bAttack = FALSE; ClearActions( CLEAR_NW_C2_DEFAULTB_GUSTWIND ); //ActionForceMoveToObject( oCaster, TRUE, 2.0f ); ActionMoveToObject( GetCurrentMaster(), TRUE, 1.1f ); DelayCommand( 1.2f, ActionDoCommand( HenchmenCombatRound(OBJECT_INVALID) ) ); } break; case X2_SPELL_AOEBEHAVIOR_IGNORE: // well ... nothing break; case X2_SPELL_AOEBEHAVIOR_GUST: // BMA-OEI 9/20/06: Disable spell casting while Polymorphed if ( GetHasEffect( EFFECT_TYPE_POLYMORPH ) == FALSE ) { bAttack = FALSE; ActionCastSpellAtLocation( SPELL_GUST_OF_WIND, GetLocation(OBJECT_SELF) ); } //ActionDoCommand( SetCommandable(TRUE) ); //SetCommandable( FALSE ); break; default: } } } } if ( bAttack == TRUE ) { if (( GetAssociateState(NW_ASC_IS_BUSY) == FALSE ) && ( GetAssociateState(NW_ASC_MODE_STAND_GROUND) == FALSE ) && ( GetAssociateState(NW_ASC_MODE_PUPPET) == FALSE )) //DBR 8/03/06 I am a puppet. I put nothing on the ActionQueue myself. { if ( ( GetNumActions(OBJECT_SELF) == 0 ) || ( GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOW ) ) { if ( GetIsObjectValid( oCaster ) == TRUE ) { if ( ( GetIsObjectValid(GetAttackTarget()) == FALSE ) && ( ( GetIsObjectValid(GetAttemptedSpellTarget()) == FALSE ) || ( GetIsEnemy(GetAttemptedSpellTarget()) == FALSE ) ) ) { HenchmenCombatRound( oCaster ); } } } } } } if ( GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT) == TRUE ) { SignalEvent( OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT) ); } } // gb_comp_userdef /* companion On User Defined */ // ChazM 12/5/05 // ChazM 12/7/05 added DoBrawl(), restructured main(), added comments // ChazM 5/18/05 reference to master now uses GetCurrentMaster() - returns master for associate or companion // BMA-OEI 7/14/06 Added EVENT_ROSTER_SPAWN_IN handler: ForceRest OnSpawnIn (Removed to prevent healing on Load Game) // DBR - 08/03/06 added support for NW_ASC_MODE_PUPPET // DBR - 08/11/06 Removed Khelgar brawling animation scripts // BMA-OEI 09/12/06 -- Added EVENT_PLAYER_CONTROL_CHANGED handler // BMA-OEI 09/20/06 -- CheckForDisabledPartyMembers(): Disable spell casting while Polymorphed // BMA-OEI 10/08/06 -- Added HandleRosterSpawnIn(): Campaign check to set Plot Flag FALSE //::////////////////////////////////////////////////// //:: X0_CH_HEN_USRDEF //:: Copyright (c) 2002 Floodgate Entertainment //::////////////////////////////////////////////////// #include "X0_INC_HENAI" #include "ginc_companion" // ----------------------------------------------------------------- // Prototypes // ----------------------------------------------------------------- // Try to cast nSpell on oMaster. returns 1 on success, 0 on failure. int CheckSpell(int nSpell, object oMaster); // Try to cast a restorative spell if the master has a spell effect // that prevents him from talking to the henchmen and asking for help (hold, fear, confusion etc') // The henchmen would also try to help other disabled henchmen. // The henchmen would try to cast dispel-magic spells to remove disabling spells from the player // unless the player told him not to do it (since it might dispel other helpful buffing spells). void CheckForDisabledPartyMembers(); // Try to cast nSpell on oMaster. returns 1 on success, 0 on failure. int CheckSpell(int nSpell, object oMaster); // Try to cast a restorative spell if the master has a spell effect // that prevents him from talking to the henchmen and asking for help (hold, fear, confusion etc') // The henchmen would also try to help other disabled henchmen. // The henchmen would try to cast dispel-magic spells to remove disabling spells from the player // unless the player told him not to do it (since it might dispel other helpful buffing spells). void CheckForDisabledPartyMembers(); // Event handler for EVENT_ROSTER_SPAWN_IN // If Campaign Flag is set and OBJECT_SELF is spawned into the PC Party, // Set Plot Flag FALSE ( Invulnerablility safety for saving/loading before CombatCutsceneCleanUp ) void HandleRosterSpawnIn(); // ----------------------------------------------------------------- // Functions // ----------------------------------------------------------------- /* int ACTION_MODE_DETECT = 0; int ACTION_MODE_STEALTH = 1; int ACTION_MODE_PARRY = 2; int ACTION_MODE_POWER_ATTACK = 3; int ACTION_MODE_IMPROVED_POWER_ATTACK = 4; int ACTION_MODE_COUNTERSPELL = 5; int ACTION_MODE_FLURRY_OF_BLOWS = 6; int ACTION_MODE_RAPID_SHOT = 7; int ACTION_MODE_COMBAT_EXPERTISE = 8; int ACTION_MODE_IMPROVED_COMBAT_EXPERTISE = 9; int ACTION_MODE_DEFENSIVE_CAST = 10; int ACTION_MODE_DIRTY_FIGHTING = 11; */ void main() { int nEvent = GetUserDefinedEventNumber(); switch (nEvent) { // ---------------------------------------------------- // Alter w/ care. These affect everyone. // ---------------------------------------------------- // To toggle on/off individually for a creature, use: // SetSpawnInCondition(int nCondition, int bValid = TRUE) // // // case EVENT_HEARTBEAT: // 1001 - NW_FLAG_HEARTBEAT_EVENT // break; // // case EVENT_PERCEIVE: // 1002 - NW_FLAG_PERCIEVE_EVENT // break; // // case EVENT_END_COMBAT_ROUND: // 1003 - NW_FLAG_END_COMBAT_ROUND_EVENT // break; // // case EVENT_DIALOGUE: // 1004 - NW_FLAG_ON_DIALOGUE_EVENT // break; // // case EVENT_ATTACKED: // 1005 - NW_FLAG_ATTACK_EVENT // break; // // case EVENT_DAMAGED: // 1006 - NW_FLAG_DAMAGED_EVENT // break; // // case EVENT_DISTURBED: // 1008 - NW_FLAG_DISTURBED_EVENT // break; // // case EVENT_SPELL_CAST_AT: // 1011 - NW_FLAG_SPELL_CAST_AT_EVENT // break; // ---------------------------------------------------- // Events specific to campaign companions. // ---------------------------------------------------- // General 2000 - 2099 // AMMON 2100 - 2199 // BISHOP 2200 - 2299 // CASAVIR 2300 - 2399 // CONSTRUCT 2400 - 2499 // ELANEE 2500 - 2599 // GROBNAR 2600 - 2699 // KHELGAR 2700 - 2799 // NEESHKA 2800 - 2899 // QARA 2900 - 2999 // SAND 3000 - 3099 // SHANDRA 3100 - 3199 // ZHJAEVE 3200 - 3299 // ---------------------------------------------------- // Alter w/ care. These affect everyone. // ---------------------------------------------------- case EVENT_ROSTER_SPAWN_IN: // 2051: Roster Member SpawnIn Event ( via Script, GUI, Load Game ) { HandleRosterSpawnIn(); break; } case EVENT_PLAYER_CONTROL_CHANGED: // 2052 { HandlePlayerControlChanged( OBJECT_SELF ); break; } case 20000: // 20000 + ACTION_MODE_DETECT { if (GetAssociateState(NW_ASC_MODE_PUPPET)==TRUE) //DBR 8/03/06 I am a puppet. I put nothing on the ActionQueue myself. break; int bDetect = GetActionMode(GetPCLeader(), ACTION_MODE_DETECT); SetActionMode(OBJECT_SELF, ACTION_MODE_DETECT, bDetect); break; } case 20001: // 20000 + ACTION_MODE_STEALTH { if (GetAssociateState(NW_ASC_MODE_PUPPET)==TRUE) //DBR 8/03/06 I am a puppet. I put nothing on the ActionQueue myself. break; int bStealth = GetActionMode(GetPCLeader(), ACTION_MODE_STEALTH); SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, bStealth); break; } // * This event is triggered whenever an NPC or PC in the party // * is disabled (or potentially disabled). // * This is a migration of a useful heartbeat routine Yaron made // * into a less AI extensive route case 46500: { CheckForDisabledPartyMembers(); break; } } } int CheckSpell(int nSpell, object oMaster) { if(GetHasSpell(nSpell)) { ClearAllActions(); ActionCastSpellAtObject(nSpell, oMaster); return 1; } return 0; } // Check whether the creature has disabling effects that are magical and therefor and can removed by // dispel magic spells. int HasDisablingMagicalEffect(object oCreature) { effect eEff = GetFirstEffect(oCreature); while(GetIsEffectValid(eEff)) { if(GetEffectType(eEff) == EFFECT_TYPE_CONFUSED || GetEffectType(eEff) == EFFECT_TYPE_PARALYZE || GetEffectType(eEff) == EFFECT_TYPE_FRIGHTENED || GetEffectType(eEff) == EFFECT_TYPE_DOMINATED || GetEffectType(eEff) == EFFECT_TYPE_DAZED || GetEffectType(eEff) == EFFECT_TYPE_STUNNED) { if(GetEffectSubType(eEff) == SUBTYPE_MAGICAL) return TRUE; // can be dispelled else return FALSE; } eEff = GetNextEffect(oCreature); } return FALSE; } // Checks a single creature for disabling effects, trying to remove them if possible. void CheckCreature(object oCreature) { // First, trying to cast specific-purpose spells and then trying more general spells. if(GetHasEffect(EFFECT_TYPE_FRIGHTENED, oCreature)) if(CheckSpell(SPELL_REMOVE_FEAR, oCreature)) return; if(GetHasEffect(EFFECT_TYPE_PARALYZE, oCreature)) if(CheckSpell(SPELL_REMOVE_PARALYSIS, oCreature)) return; if(GetHasEffect(EFFECT_TYPE_CONFUSED, oCreature) || GetHasEffect(EFFECT_TYPE_FRIGHTENED, oCreature) || GetHasEffect(EFFECT_TYPE_PARALYZE, oCreature) || GetHasEffect(EFFECT_TYPE_DOMINATED, oCreature) || GetHasEffect(EFFECT_TYPE_DAZED, oCreature) || GetHasEffect(EFFECT_TYPE_STUNNED, oCreature)) { if(CheckSpell(SPELL_GREATER_RESTORATION, oCreature)) return; if(CheckSpell(SPELL_RESTORATION, oCreature)) return; if(HasDisablingMagicalEffect(oCreature) && GetLocalInt(OBJECT_SELF, "X2_HENCH_DO_NOT_DISPEL") == 0) { if(CheckSpell(SPELL_GREATER_DISPELLING, oCreature)) return; if(CheckSpell(SPELL_DISPEL_MAGIC, oCreature)) return; if(CheckSpell(SPELL_LESSER_DISPEL, oCreature)) return; } } } void CheckForDisabledPartyMembers() { // BMA-OEI 9/20/06: Disable spell casting while Polymorphed if ( GetHasEffect( EFFECT_TYPE_POLYMORPH ) == TRUE ) { return; } object oMaster = GetCurrentMaster(); //GetPCLeader(OBJECT_SELF); if(oMaster != OBJECT_INVALID) CheckCreature(oMaster); int i = 1; object oHench = GetHenchman(oMaster, i); while(oHench != OBJECT_INVALID) { CheckCreature(oHench); i++; oHench = GetHenchman(oMaster, i); } } // Event handler for EVENT_ROSTER_SPAWN_IN // If Campaign Flag is set and OBJECT_SELF is spawned into the PC Party, // Set Plot Flag FALSE ( Invulnerablility safety for saving/loading before CombatCutsceneCleanUp ) void HandleRosterSpawnIn() { // Campaign flag set OnModuleLoad if ( GetGlobalInt( CAMPAIGN_SWITCH_UNPLOT_ON_ROSTER_SPAWN ) == TRUE ) { // If OBJECT_SELF is in FirstPC's Party if ( GetIsObjectInParty( OBJECT_SELF ) == TRUE ) { SetPlotFlag( OBJECT_SELF, FALSE ); } } } //gb_death_talk /* when creature dead, a conversation starts */ #include "nw_i0_plot" void main() { string sTalkerTag = GetLocalString(OBJECT_SELF, "TalkerTag"); string sConversation = GetLocalString(OBJECT_SELF, "Conversation"); object oNPC = GetObjectByTag(sTalkerTag); object oPC = GetNearestPC(); if (sTalkerTag == "") { oNPC = oPC; } AssignCommand(oNPC, ClearAllActions(TRUE)); //PrintString(GetName (oNPC) + "starting convo " + sConversation + " with " + GetName(oPC)); AssignCommand(oNPC, ActionStartConversation(oPC, sConversation)); } // gb_dm_co //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT4 /* Default OnConversation event handler for NPCs. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/22/2002 //::////////////////////////////////////////////////// #include "nw_i0_generic" void main() { // * if petrified, jump out if (GetHasEffect(EFFECT_TYPE_PETRIFY, OBJECT_SELF) == TRUE) { return; } // * If dead, exit directly. if (GetIsDead(OBJECT_SELF) == TRUE) { return; } // See if what we just 'heard' matches any of our // predefined patterns int nMatch = GetListenPatternNumber(); object oShouter = GetLastSpeaker(); if (nMatch == -1) { // Not a match -- start an ordinary conversation if (GetCommandable(OBJECT_SELF)) { ClearActions(CLEAR_NW_C2_DEFAULT4_29); BeginConversation(); } else // * July 31 2004 // * If only charmed then allow conversation // * so you can have a better chance of convincing // * people of lowering prices if (GetHasEffect(EFFECT_TYPE_CHARMED) == TRUE) { ClearActions(CLEAR_NW_C2_DEFAULT4_29); BeginConversation(); } } // Respond to shouts from friendly non-PCs only else if (GetIsObjectValid(oShouter) && !GetIsPC(oShouter) && GetIsFriend(oShouter)) { object oIntruder = OBJECT_INVALID; // Determine the intruder if any if(nMatch == 4) { oIntruder = GetLocalObject(oShouter, "NW_BLOCKER_INTRUDER"); } else if (nMatch == 5) { oIntruder = GetLastHostileActor(oShouter); if(!GetIsObjectValid(oIntruder)) { oIntruder = GetAttemptedAttackTarget(); if(!GetIsObjectValid(oIntruder)) { oIntruder = GetAttemptedSpellTarget(); if(!GetIsObjectValid(oIntruder)) { oIntruder = OBJECT_INVALID; } } } } // Actually respond to the shout RespondToShout(oShouter, nMatch, oIntruder); } object oPC = GetPCSpeaker(); if ((oPC == oShouter) && (nMatch == 2000)) { string sParam = GetMatchedSubstring(0); string sOut = "DM heard: " + sParam; PrintString(sOut); SpeakString(sOut); SetLocalString(oPC, "dm_param", sParam); } // Send the user-defined event if appropriate if(GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT)) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_DIALOGUE)); } } // gb_dm_sp //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); SetListenPattern(OBJECT_SELF, "**", 2000); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } // gb_do_nothing /* creature do-nothing script */ // ChazM 4/19/06 void main() { // do utterly nothing! } // gb_endcmbt_sp /* Standard spawn script that fires User Defined Event 1003 in the OnCombatRoundEnd */ // ChazM 5/8/05 //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } // gb_follow_hb /* creature will follow another creature stored as local obj "Leader" */ // ChazM 9/12/05 void DoFollow(object oMaster, float fDistance) { // check not doing some other action if(GetIsObjectValid(oMaster) && GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW && GetCurrentAction(OBJECT_SELF) != ACTION_DISABLETRAP && GetCurrentAction(OBJECT_SELF) != ACTION_OPENLOCK && GetCurrentAction(OBJECT_SELF) != ACTION_REST && GetCurrentAction(OBJECT_SELF) != ACTION_ATTACKOBJECT) { // check not involved in any combat related stuff if(!GetIsObjectValid(GetAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN))) { // we must not be following any more, so follow again. if(GetDistanceToObject(oMaster) > fDistance) { //ClearActions(CLEAR_NW_CH_AC1_49); ActionForceFollowObject(oMaster, fDistance); } } } } void main() { object oLeader = GetLocalObject(OBJECT_SELF, "Leader"); float fDistance = GetLocalFloat(OBJECT_SELF, "FollowDistance"); DoFollow(oLeader, fDistance); ExecuteScript("nw_c2_default1", OBJECT_SELF); } // gb_heartbeat_sp /* standard spawn script that fires User Defined Event 1001 in the OnHeartbeat */ // ChazM 3/8/05 //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Attacked //:: gb_pcai_attack //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptAttacked"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_attack", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Pathing Blocked //:: gb_pcai_block //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptOnBlocked"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_block", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: //:: gb_pcai_combat //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptEndRound"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_combat", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Dialog //:: gb_pcai_conv //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptDialogue"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_conv", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Damaged //:: gb_pcai_damage //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptDamaged"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_damage", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnDeath //:: gb_pcai_death //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptDeath"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_death", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Inventory Disturbed //:: gb_pcai_distrb //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptDisturbed"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_distrb", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnHeartbeat //:: gb_pcai_heart //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptHeartbeat"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_heart", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Shout //:: gb_pcai_attack //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptOnShout"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_onshout", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: On Perception //:: gb_pcai_percep //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptOnNotice"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_percep", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnRested //:: gb_pcai_rest //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptRested"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_rest", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnSpawnIn //:: gb_pcai_spawn //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptSpawn"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_spawn", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnSpellCastAt OMFWTF OH NOES!!!11111 //:: gb_pcai_spell //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptSpellAt"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_spell", OBJECT_SELF); } //::////////////////////////////////////////////////////////////////////////// //:: Player Character Script: OnUserDefined //:: gb_pcai_usrdef //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* Temp placeholder script */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: Brock Heinz //:: Created On: 09/26/05 //::////////////////////////////////////////////////////////////////////////// void main() { string strScriptName = "ScriptUserDefine"; string strName = GetName(OBJECT_SELF); if ( GetIsPC( OBJECT_SELF ) ) { ActionSpeakString( "WARNING! Player CONTROLLED object " +strName+ " running " + strScriptName ); } else if ( GetIsOwnedByPlayer(OBJECT_SELF) ) { ActionSpeakString( "Player OWNED object " +strName+ " running " + strScriptName ); } else { ActionSpeakString( "Player UNOWNED object " +strName+ " running " + strScriptName ); } ExecuteScript("gb_comp_usrdef", OBJECT_SELF); } // gb_player_ud /* user defined events template */ // ChazM 9/5/06 don't have leader follow himself // BMA-OEI 09/12/06 -- Added EVENT_PLAYER_CONTROL_CHANGED handler #include "ginc_companion" #include "ginc_debug" #include "x0_i0_assoc" // this includes: GetFollowDistance() void main() { int iEvent = GetUserDefinedEventNumber(); switch (iEvent) { case EVENT_HEARTBEAT: // 1001 break; case EVENT_PERCEIVE: // 1002 break; case EVENT_END_COMBAT_ROUND: // 1003 break; case EVENT_DIALOGUE: // 1004 break; case EVENT_ATTACKED: // 1005 break; case EVENT_DAMAGED: // 1006 break; case EVENT_DISTURBED: // 1008 break; case EVENT_SPELL_CAST_AT: // 1011 break; case EVENT_PLAYER_CONTROL_CHANGED: // 2052 { HandlePlayerControlChanged( OBJECT_SELF ); break; } } } // gb_ranged_sp // // Set the creature's ranged combat flag // EPF 1/26/06 //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript // ChazM 6/20/05 ambient anims flag set on spawn for encounter cratures. // ChazM 1/6/06 modified call to WalkWayPoints() #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(FALSE, "spawn"); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // if (GetIsEncounterCreature()) SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, TRUE); // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } //::////////////////////////////////////////////////////////////////////////// //:: Creature Script: Set Associate Listen Patterns //:: gb_setassociatelistenpatterns //:: Copyright (c) 2005 Obsidian Entertainment Inc. //::////////////////////////////////////////////////////////////////////////// /* This script called by SetAssociateListenPatterns() script command Sets up the special henchmen listening patterns, now also used for party companions as well */ //::////////////////////////////////////////////////////////////////////////// //:: Created By: ChazM //:: Created On: 11/21/05 //::////////////////////////////////////////////////////////////////////////// // ChazM 5/5/06 - commented out debug ActionSpeakString() void main() { //string strScriptName = "gb_setassociatelistenpatterns"; //string strName = GetName(OBJECT_SELF); //ActionSpeakString( strName+ " running " + strScriptName ); //Sets up the special henchmen listening patterns SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_GUARDMASTER", ASSOCIATE_COMMAND_GUARDMASTER); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_STANDGROUND", ASSOCIATE_COMMAND_STANDGROUND); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_ATTACKNEAREST", ASSOCIATE_COMMAND_ATTACKNEAREST); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_HEALMASTER", ASSOCIATE_COMMAND_HEALMASTER); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_FOLLOWMASTER", ASSOCIATE_COMMAND_FOLLOWMASTER); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_MASTERFAILEDLOCKPICK", ASSOCIATE_COMMAND_MASTERFAILEDLOCKPICK); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_MASTERUNDERATTACK", ASSOCIATE_COMMAND_MASTERUNDERATTACK); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_UNPOSSESSFAMILIAR", ASSOCIATE_COMMAND_UNPOSSESSFAMILIAR); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_MASTERSAWTRAP", ASSOCIATE_COMMAND_MASTERSAWTRAP); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_MASTERATTACKEDOTHER", ASSOCIATE_COMMAND_MASTERATTACKEDOTHER); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_MASTERGOINGTOBEATTACKED",ASSOCIATE_COMMAND_MASTERGOINGTOBEATTACKED); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_LEAVEPARTY", ASSOCIATE_COMMAND_LEAVEPARTY); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_PICKLOCK", ASSOCIATE_COMMAND_PICKLOCK); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_INVENTORY", ASSOCIATE_COMMAND_INVENTORY); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_DISARMTRAP", ASSOCIATE_COMMAND_DISARMTRAP); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_TOGGLECASTING", ASSOCIATE_COMMAND_TOGGLECASTING); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_TOGGLESTEALTH", ASSOCIATE_COMMAND_TOGGLESTEALTH); SetListenPattern (OBJECT_SELF, "ASSOCIATE_COMMAND_TOGGLESEARCH", ASSOCIATE_COMMAND_TOGGLESEARCH); } // gb_spawn_dead_sp /* This spawns in a creature dead */ // FAB 2/8 // ChazM 3/8/05 void main() { SetIsDestroyable( FALSE,FALSE,FALSE ); effect eFX = EffectDeath(); ApplyEffectToObject( DURATION_TYPE_INSTANT,eFX,OBJECT_SELF ); } // gb_stealthy_sp // Sets a character's stealthy combat flag. // EPF 1/26/06 //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript // ChazM 6/20/05 ambient anims flag set on spawn for encounter cratures. // ChazM 1/6/06 modified call to WalkWayPoints() #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(FALSE, "spawn"); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // if (GetIsEncounterCreature()) SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, TRUE); // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } // gb_surrender_sp //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * // SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * //SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } //gb_surrender_ud /* When creature drop below percentage of HP, he surrenders and speaks w/ the nearest PC How to use: make copy of this script and assign it and gb_surrender_sp to creature. works best if creature is immortal */ #include "x0_i0_partywide" //has SurrenderAllToEnemies() #include "ginc_misc" const float HP_PERCENT_SURRENDER = 25.0f; void main() { int nUser = GetUserDefinedEventNumber(); if(nUser == 1001) //HEARTBEAT { } else if(nUser == 1002) // PERCEIVE { } else if(nUser == 1003) // END OF COMBAT { } else if(nUser == 1004) // ON DIALOGUE { } else if(nUser == 1005) // ATTACKED { } else if(nUser == 1006) // DAMAGED { if (IsMarkedAsDone()) return; int nMaxHP = GetMaxHitPoints(); int nCurrHP = GetCurrentHitPoints(); int nPercentofMaxHP = FloatToInt((IntToFloat(nMaxHP) * (HP_PERCENT_SURRENDER/100.0f))); // * generic surrender should only fire once if((GetIsDead(OBJECT_SELF) == FALSE) && ((nCurrHP <= nPercentofMaxHP) || (nCurrHP <=1))) { MarkAsDone(); PrintString (GetName(OBJECT_SELF) + " surrenders!"); SurrenderAllToEnemies(OBJECT_SELF); object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC); SurrenderAllToEnemies(oPC); ActionStartConversation(oPC); } } else if(nUser == 1007) // DEATH { } else if(nUser == 1008) // DISTURBED { } } //gb_troll_dmg //Damge script for trolls, making them un-killable by anything but fire or acid. //DBR 6/1/6 // DBR 7/12/06 - bugfix, made sure the damaged event fires even if down to 1HP. #include "nw_i0_generic" void TrollRessurect() { ClearAllActions(TRUE); ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints()),OBJECT_SELF); ClearAllActions(TRUE); SetLocalInt(OBJECT_SELF,"gb_troll_dmg_down",0); DetermineCombatRound(); } void main() { int nAcid = GetDamageDealtByType(DAMAGE_TYPE_ACID)+1; //returns -1 if none is dealt, 0 if acid damage was dealt, but a very meager amount int nFire = GetDamageDealtByType(DAMAGE_TYPE_FIRE)+1; if ((nFire+nAcid)!=0) { if ((GetCurrentHitPoints()<=nAcid+nFire+1)||GetLocalInt(OBJECT_SELF,"gb_troll_dmg_down")) //if I am knocked down or near death, this kills me. { SetImmortal(OBJECT_SELF,FALSE); object oTroll = OBJECT_SELF; AssignCommand(GetLastDamager(),ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDeath(),oTroll)); return; } } //If I'm down, put out a fake "weapon ineffective" message. if (GetLocalInt(OBJECT_SELF,"gb_troll_dmg_down")==1) { FloatingTextStrRefOnCreature(4725,GetLastDamager(),FALSE); } else if (GetCurrentHitPoints()<=1)//If I've been beaten down, but am not in a knocked down state, put me in one. { int nDuration = GetMaxHitPoints()/3; ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectKnockdown(),OBJECT_SELF,IntToFloat(nDuration)); SetLocalInt(OBJECT_SELF,"gb_troll_dmg_down",1); DelayCommand(IntToFloat(nDuration+1),TrollRessurect()); } //otherwise, heal 1HP so that the onDamageevent does fire again. ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(1),OBJECT_SELF); ExecuteScript("nw_c2_default6",OBJECT_SELF); } // gb_wanderer_sp /* Standard spawn script that causes creature to use mobile ambient animations. */ // ChazM 3/8/05 //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT9 /* * Default OnSpawn handler with XP1 revisions. * This corresponds to and produces the same results * as the default OnSpawn handler in the OC. * * This can be used to customize creature behavior in three main ways: * * - Uncomment the existing lines of code to activate certain * common desired behaviors from the moment when the creature * spawns in. * * - Uncomment the user-defined event signals to cause the * creature to fire events that you can then handle with * a custom OnUserDefined event handler script. * * - Add new code _at the end_ to alter the initial * behavior in a more customized way. */ //::////////////////////////////////////////////////// //:: Copyright (c) 2002 Floodgate Entertainment //:: Created By: Naomi Novik //:: Created On: 12/11/2002 //::////////////////////////////////////////////////// //:: Updated 2003-08-20 Georg Zoeller: Added check for variables to active spawn in conditions without changing the spawnscript #include "x0_i0_anims" // #include "x0_i0_walkway" - in x0_i0_anims #include "x0_i0_treasure" #include "x2_inc_switches" void main() { // ***** Spawn-In Conditions ***** // // * REMOVE COMMENTS (// ) before the "Set..." functions to activate // * them. Do NOT touch lines commented out with // *, those are // * real comments for information. // * This causes the creature to say a one-line greeting in their // * conversation file upon perceiving the player. Put [NW_D2_GenCheck] // * in the "Text Seen When" field of the greeting in the conversation // * file. Don't attach any player responses. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION); // * Same as above, but for hostile creatures to make them say // * a line before attacking. // * // SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION); // * This NPC will attack when its allies call for help // * // SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET); // * If the NPC has the Hide skill they will go into stealth mode // * while doing WalkWayPoints(). // * // SetSpawnInCondition(NW_FLAG_STEALTH); //-------------------------------------------------------------------------- // Enable stealth mode by setting a variable on the creature // Great for ambushes // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE) { SetSpawnInCondition(NW_FLAG_STEALTH); } // * Same, but for Search mode // * // SetSpawnInCondition(NW_FLAG_SEARCH); //-------------------------------------------------------------------------- // Make creature enter search mode after spawning by setting a variable // Great for guards, etc // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_SEARCH) == TRUE) { SetSpawnInCondition(NW_FLAG_SEARCH); } // * This will set the NPC to give a warning to non-enemies // * before attacking. // * NN -- no clue what this really does yet // * // SetSpawnInCondition(NW_FLAG_SET_WARNINGS); // * Separate the NPC's waypoints into day & night. // * See comment on WalkWayPoints() for use. // * // SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING); // * If this is set, the NPC will appear using the "EffectAppear" // * animation instead of fading in, *IF* SetListeningPatterns() // * is called below. // * //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION); // * This will cause an NPC to use common animations it possesses, // * and use social ones to any other nearby friendly NPCs. // * // SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable immobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE) == TRUE) { SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // * Same as above, except NPC will wander randomly around the // * area. // * SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); //-------------------------------------------------------------------------- // Enable mobile ambient animations by setting a variable // See x2_inc_switches for more information about this //-------------------------------------------------------------------------- if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_AMBIENT) == TRUE) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS); } // **** Animation Conditions **** // // * These are extra conditions you can put on creatures with ambient // * animations. // * Civilized creatures interact with placeables in // * their area that have the tag "NW_INTERACTIVE" // * and "talk" to each other. // * // * Humanoid races are civilized by default, so only // * set this flag for monster races that you want to // * behave the same way. // SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED); // * If this flag is set, this creature will constantly // * be acting. Otherwise, creatures will only start // * performing their ambient animations when they // * first perceive a player, and they will stop when // * the player moves away. // SetAnimationCondition(NW_ANIM_FLAG_CONSTANT); // * Civilized creatures with this flag set will // * randomly use a few voicechats. It's a good // * idea to avoid putting this on multiple // * creatures using the same voiceset. // SetAnimationCondition(NW_ANIM_FLAG_CHATTER); // * Creatures with _immobile_ ambient animations // * can have this flag set to make them mobile in a // * close range. They will never leave their immediate // * area, but will move around in it, frequently // * returning to their starting point. // * // * Note that creatures spawned inside interior areas // * that contain a waypoint with one of the tags // * "NW_HOME", "NW_TAVERN", "NW_SHOP" will automatically // * have this condition set. // SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE); // **** Special Combat Tactics *****// // * These are special flags that can be set on creatures to // * make them follow certain specialized combat tactics. // * NOTE: ONLY ONE OF THESE SHOULD BE SET ON A SINGLE CREATURE. // * Ranged attacker // * Will attempt to stay at ranged distance from their // * target. // SetCombatCondition(X0_COMBAT_FLAG_RANGED); // * Defensive attacker // * Will use defensive combat feats and parry // SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE); // * Ambusher // * Will go stealthy/invisible and attack, then // * run away and try to go stealthy again before // * attacking anew. // SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER); // * Cowardly // * Cowardly creatures will attempt to flee // * attackers. // SetCombatCondition(X0_COMBAT_FLAG_COWARDLY); // **** Escape Commands ***** // // * NOTE: ONLY ONE OF THE FOLLOWING SHOULD EVER BE SET AT ONE TIME. // * NOTE2: Not clear that these actually work. -- NN // * Flee to a way point and return a short time later. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // * Flee to a way point and do not return. // * // SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // * Teleport to safety and do not return. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // * Teleport to safety and return a short time later. // * // SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // ***** CUSTOM USER DEFINED EVENTS ***** / /* If you uncomment any of these conditions, the creature will fire a specific user-defined event number on each event. That will then allow you to write custom code in the "OnUserDefinedEvent" handler script to go on top of the default NPC behaviors for that event. Example: I want to add some custom behavior to my NPC when they are damaged. I uncomment the "NW_FLAG_DAMAGED_EVENT", then create a new user-defined script that has something like this in it: if (GetUserDefinedEventNumber() == 1006) { // Custom code for my NPC to execute when it's damaged } These user-defined events are in the range 1001-1007. */ // * Fire User Defined Event 1001 in the OnHeartbeat // * // SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); // * Fire User Defined Event 1002 // * // SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); // * Fire User Defined Event 1005 // * // SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); // * Fire User Defined Event 1006 // * // SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); // * Fire User Defined Event 1008 // * // SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); // * Fire User Defined Event 1003 // * // SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); // * Fire User Defined Event 1004 // * // SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); // ***** DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) ***** // // * Goes through and sets up which shouts the NPC will listen to. // * SetListeningPatterns(); // * Walk among a set of waypoints. // * 1. Find waypoints with the tag "WP_" + NPC TAG + "_##" and walk // * among them in order. // * 2. If the tag of the Way Point is "POST_" + NPC TAG, stay there // * and return to it after combat. // // * Optional Parameters: // * void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) // // * If "NW_FLAG_DAY_NIGHT_POSTING" is set above, you can also // * create waypoints with the tags "WN_" + NPC Tag + "_##" // * and those will be walked at night. (The standard waypoints // * will be walked during the day.) // * The night "posting" waypoint tag is simply "NIGHT_" + NPC tag. WalkWayPoints(); //* Create a small amount of treasure on the creature if ((GetLocalInt(GetModule(), "X2_L_NOTREASURE") == FALSE) && (GetLocalInt(OBJECT_SELF, "X2_L_NOTREASURE") == FALSE) ) { CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); } // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // * If Incorporeal, apply changes if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) { effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); eConceal = ExtraordinaryEffect(eConceal); effect eGhost = EffectCutsceneGhost(); eGhost = ExtraordinaryEffect(eGhost); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); } } Global Conditional // gc_align_chaotic.nss /* Check if player's alignment is Chaotic */ // BMA-OEI 7/25/05 const int ALIGN_VALUE_CHAOTIC = 33; int StartingConditional() { object oPC = GetPCSpeaker(); int nAlignment = GetLawChaosValue(oPC); // 100(lawful) - 0(chaotic) if (nAlignment <= ALIGN_VALUE_CHAOTIC) { return TRUE; } else { return FALSE; } } // gc_align_evil.nss /* Check if player's alignment is Evil */ // BMA-OEI 7/25/05 const int ALIGN_VALUE_EVIL = 33; int StartingConditional() { object oPC = GetPCSpeaker(); int nAlignment = GetGoodEvilValue(oPC); // 100(good) - 0(evil) if (nAlignment <= ALIGN_VALUE_EVIL) { return TRUE; } else { return FALSE; } } // gc_align_good.nss /* Check if player's alignment is Good */ // BMA-OEI 7/25/05 const int ALIGN_VALUE_GOOD = 67; int StartingConditional() { object oPC = GetPCSpeaker(); int nAlignment = GetGoodEvilValue(oPC); // 100(good) - 0(evil) if (nAlignment >= ALIGN_VALUE_GOOD) { return TRUE; } else { return FALSE; } } // gc_align_lawful.nss /* Check if player's alignment is Lawful */ // BMA-OEI 7/25/05 const int ALIGN_VALUE_LAWFUL = 67; int StartingConditional() { object oPC = GetPCSpeaker(); int nAlignment = GetLawChaosValue(oPC); // 100(lawful) - 0(chaotic) if (nAlignment >= ALIGN_VALUE_LAWFUL) { return TRUE; } else { return FALSE; } } // gc_alignment /* This checks if player's alignment is greater than or equal to nCheck. Parameters: int nCheck = Checks if alignment of player is greater than defines. On a scale of 3 (Saintly) to -3 (Fiendish) Or equivalently, 3 (Really, really lawful), to -3 (incredibly chaotic) So the standard "Is the PC good?" check would use a value of 0 for nCheck. Same for "Is the PC evil," but you'd use a NOT with this script call -- as in "Is the PC NOT good?" int bLawChaosAxis = 0 means check Good/Evil axis, 1 means check Law/Chaos axis */ // FAB 10/5 // EPF 6/6/05 -- changed some function calls, modified param name int StartingConditional(int nCheck, int bLawChaosAxis) { object oPC = GetPCSpeaker(); int nAlignCheck; // Set up alignment to check switch ( nCheck ) { case -3: nAlignCheck = 5; // -84 Later on break; case -2: nAlignCheck = 15; // -59 Later on break; case -1: nAlignCheck = 25; // -24 Later on break; case 0: nAlignCheck = 50; // 0 Later on break; case 1: nAlignCheck = 75; // 25 Later on break; case 2: nAlignCheck = 85; // 60 Later on break; case 3: nAlignCheck = 99; // 85 Later on break; } if ( bLawChaosAxis == 0 ) { if ( GetGoodEvilValue(oPC) >= nAlignCheck ) return TRUE; } else { if ( GetLawChaosValue(oPC) >= nCheck ) return TRUE; } return FALSE; } // gc_area // // True if creature with tag sTarget is in area with tag sArea. Can use parameter constants like $OBJECT_SELF as defined in ginc_param_const. // Empty string for sTarget defaults to OBJECT_SELF. // // EPF 8/2/05 #include "ginc_misc" int StartingConditional(string sArea, string sTarget) { object oTarget = GetTarget(sTarget); object oArea = GetObjectByTag(sArea); if(sTarget == "") { oTarget = OBJECT_SELF; } if(!GetIsObjectValid(oArea) || !GetIsObjectValid(oTarget)) { return FALSE; } if(GetArea(oTarget) == oArea) { return TRUE; } return FALSE; } // gc_background // // Check background trait for the PC. Background constants are as follows: // BACKGROUND_NONE = 0; // BACKGROUND_BULLY = 1; // BACKGROUND_COMPLEX = 2; // BACKGROUND_DEVOUT = 3; // BACKGROUND_FARMER = 4; // BACKGROUND_LADYSMAN = 5; // BACKGROUND_THEFLIRT = 6; // BACKGROUND_MILITIA = 7; // BACKGROUND_NATURALLEADER = 8; // BACKGROUND_TALETELLER = 9; // BACKGROUND_TROUBLEMAKER = 10; // BACKGROUND_WILDCHILD = 11; // BACKGROUND_WIZARDSAPPRENTICE = 12; // EPF 2/22/06 int StartingConditional(int nBackground) { object oPC = GetFactionLeader(GetPCSpeaker()); return GetCharBackground(oPC) == nBackground; } // gc_check_class(int nClass) /* This script checks to see if the player (PC_Speaker) has any levels of a certain class nClass = The integer of which class to check for (list boxes will be done later) */ // FAB 10/11 // BMA-OEI 8/23/05 added warlock check int StartingConditional(int nClass) { object oPC = GetPCSpeaker(); int nNewClass; switch ( nClass ) { case 0: // BARBARIAN nNewClass = CLASS_TYPE_BARBARIAN; break; case 1: // BARD nNewClass = CLASS_TYPE_BARD; break; case 2: // CLERIC nNewClass = CLASS_TYPE_CLERIC; break; case 3: // DRUID nNewClass = CLASS_TYPE_DRUID; break; case 4: // FIGHTER nNewClass = CLASS_TYPE_FIGHTER; break; case 5: // MONK nNewClass = CLASS_TYPE_MONK; break; case 6: // PALADIN nNewClass = CLASS_TYPE_PALADIN; break; case 7: // RANGER nNewClass = CLASS_TYPE_RANGER; break; case 8: // ROGUE nNewClass = CLASS_TYPE_ROGUE; break; case 9: // SORCERER nNewClass = CLASS_TYPE_SORCERER; break; case 10: // WIZARD nNewClass = CLASS_TYPE_WIZARD; break; case 11: // WARLOCK nNewClass = CLASS_TYPE_WARLOCK; break; } if (GetLevelByClass(nNewClass,oPC) != 0) { return TRUE; } else { return FALSE; } } // gc_check_class_level /* This script checks to see if the player (PC_Speaker) has at least X levels of a certain class nClass = The integer of which class to check for (list boxes will be done later) */ // TDE 3/7/06 int StartingConditional(int nClass, int nLevel) { object oPC = GetPCSpeaker(); int nNewClass; switch ( nClass ) { case 0: // BARBARIAN nNewClass = CLASS_TYPE_BARBARIAN; break; case 1: // BARD nNewClass = CLASS_TYPE_BARD; break; case 2: // CLERIC nNewClass = CLASS_TYPE_CLERIC; break; case 3: // DRUID nNewClass = CLASS_TYPE_DRUID; break; case 4: // FIGHTER nNewClass = CLASS_TYPE_FIGHTER; break; case 5: // MONK nNewClass = CLASS_TYPE_MONK; break; case 6: // PALADIN nNewClass = CLASS_TYPE_PALADIN; break; case 7: // RANGER nNewClass = CLASS_TYPE_RANGER; break; case 8: // ROGUE nNewClass = CLASS_TYPE_ROGUE; break; case 9: // SORCERER nNewClass = CLASS_TYPE_SORCERER; break; case 10: // WIZARD nNewClass = CLASS_TYPE_WIZARD; break; case 11: // WARLOCK nNewClass = CLASS_TYPE_WARLOCK; break; } if (GetLevelByClass(nNewClass,oPC) >= nLevel) { return TRUE; } else { return FALSE; } } // gc_check_classpr /* This script checks to see if the player (PC_Speaker) has any levels of a certain prestige class nClass = The integer of which class to check for (list boxes will be done later) */ // FAB 10/11 int StartingConditional(int nClass) { object oPC = GetPCSpeaker(); int nPrestigeClass; switch ( nClass ) { case 0: // ARCANE_ARCHER nPrestigeClass = CLASS_TYPE_ARCANE_ARCHER; break; case 1: // ARCANE_TRICKSTER //nPrestigeClass = CLASS_TYPE_ARCANE_TRICKSTER; break; case 2: // ASSASSIN nPrestigeClass = CLASS_TYPE_ASSASSIN; break; case 3: // BLACKGUARD nPrestigeClass = CLASS_TYPE_BLACKGUARD; break; case 4: // CAVALIER //nPrestigeClass = CLASS_TYPE_CAVALIER; break; case 5: // CONTEMPLATIVE //nPrestigeClass = CLASS_TYPE_CONTEMPLATIVE; break; case 6: // DIVINECHAMPION nPrestigeClass = CLASS_TYPE_DIVINECHAMPION; break; case 7: // DRAGONDISCIPLE nPrestigeClass = CLASS_TYPE_DRAGONDISCIPLE; break; case 8: // DWARVENDEFENDER nPrestigeClass = CLASS_TYPE_DWARVENDEFENDER; break; case 9: // FRENZIED_BERSERKER //nPrestigeClass = CLASS_TYPE_FRENZIED_BERSERKER; break; case 10: // HARPER nPrestigeClass = CLASS_TYPE_HARPER; break; case 11: // MYSTIC_THEURGE //nPrestigeClass = CLASS_TYPE_MYSTIC_THEURGE; break; case 12: // PALEMASTER nPrestigeClass = CLASS_TYPE_PALEMASTER; break; case 13: // SACRED_FIST //nPrestigeClass = CLASS_TYPE_SACRED_FIST; break; case 14: // SHADOW_THIEF //nPrestigeClass = CLASS_TYPE_SHADOW_THIEF; break; case 15: // SHADOWDANCER nPrestigeClass = CLASS_TYPE_SHADOWDANCER; break; case 16: // SHIFTER nPrestigeClass = CLASS_TYPE_SHIFTER; break; case 17: // WEAPON_MASTER nPrestigeClass = CLASS_TYPE_WEAPON_MASTER; break; } if ( GetLevelByClass(nPrestigeClass,oPC) != 0 ) return TRUE; return FALSE; } // gc_check_cls_lvl (int nClass, int nLevel) /* This script checks to see if the player (PC_Speaker) has a specific number of levels of a certain class nClass = The integer of which class to check for (list boxes will be done later) nLevel = The integer of how many levels or greater the character must have. */ // FAB 10/11 // BMA-OEI 8/23/05 added warlock check // FAB 9/20/05 made a new script and added second param int StartingConditional(int nClass, int nLevel) { object oPC = GetPCSpeaker(); int nNewClass; switch ( nClass ) { case 0: // BARBARIAN nNewClass = CLASS_TYPE_BARBARIAN; break; case 1: // BARD nNewClass = CLASS_TYPE_BARD; break; case 2: // CLERIC nNewClass = CLASS_TYPE_CLERIC; break; case 3: // DRUID nNewClass = CLASS_TYPE_DRUID; break; case 4: // FIGHTER nNewClass = CLASS_TYPE_FIGHTER; break; case 5: // MONK nNewClass = CLASS_TYPE_MONK; break; case 6: // PALADIN nNewClass = CLASS_TYPE_PALADIN; break; case 7: // RANGER nNewClass = CLASS_TYPE_RANGER; break; case 8: // ROGUE nNewClass = CLASS_TYPE_ROGUE; break; case 9: // SORCERER nNewClass = CLASS_TYPE_SORCERER; break; case 10: // WIZARD nNewClass = CLASS_TYPE_WIZARD; break; case 11: // WARLOCK nNewClass = CLASS_TYPE_WARLOCK; break; } if (GetLevelByClass(nNewClass,oPC) >= nLevel) { return TRUE; } else { return FALSE; } } // gc_check_gold /* This script checks to see if the PC has more than a certain amount of gold nGold = The amount of gold you want to make sure the player has nMP = If in MP - set this to 1 if you want to make sure all players have enough gold */ // FAB 10/5 int StartingConditional(int nGold, int nMP) { object oPC = GetPCSpeaker(); if ( nMP == 0 ) { if ( GetGold(oPC) >= nGold ) return TRUE; } else { oPC = GetFirstPC(); while( GetIsObjectValid(oPC) ) { if( GetGold(oPC) < nGold ) return FALSE; oPC = GetNextPC(); } return TRUE; } return FALSE; } // gc_check_item /* This script checks to see if the PC has an item in their inventory sItem = The tag name you want to check to see if the PC has bCheckParty = TRUE if you want to check the entire party for possession of the item */ // FAB 10/5 // EPF 3/13/06 -- second parameter now used to check and see if the item is held by anyone in the party // also checks the PC Speaker instead of the first PC if bCheckParty is FALSE. int StartingConditional(string sItem, int bCheckParty) { object oPC = GetPCSpeaker(); object oFM; if (!bCheckParty) { return GetIsObjectValid(GetItemPossessedBy(GetPCSpeaker(),sItem)); } else { oFM = GetFirstFactionMember(oPC, FALSE); while( GetIsObjectValid(oFM) ) { if(GetIsObjectValid(GetItemPossessedBy(oFM,sItem)) ) return TRUE; oFM = GetNextFactionMember(oPC, FALSE); } } return FALSE; } // gc_check_level /* This script checks to see if the PC's level is equal to or greater than a value nLevel = The tag name you want to check to see if the PC has nMP = If in MP - set this to 1 if you want to make sure all players are the appropriate level */ // FAB 10/5 int StartingConditional(int nLevel, int nMP) { object oPC = GetPCSpeaker(); if ( nMP == 0 ) { if ( GetHitDice(oPC) >= nLevel ) return TRUE; } else { oPC = GetFirstPC(); while( GetIsObjectValid(oPC) ) { if( GetHitDice(oPC) < nLevel ) return FALSE; oPC = GetNextPC(); } return TRUE; } return FALSE; } // gc_check_quest /* This script checks the quest states for a PC sQuest = This is the quest number that will be checked. "<" and ">" can be used. nMP = If in MP - set this to 1 if you want to make sure all players meet the quest test. */ // FAB 10/5 int StartingConditional(string sItem, int nMP) { object oPC = GetPCSpeaker(); if ( nMP == 0 ) { if ( GetIsObjectValid(GetItemPossessedBy(GetFirstPC(),sItem)) ) return TRUE; } else { oPC = GetFirstPC(); while( GetIsObjectValid(oPC) ) { if( !GetIsObjectValid(GetItemPossessedBy(GetFirstPC(),sItem)) ) return FALSE; oPC = GetNextPC(); } return TRUE; } return FALSE; } // gc_check_race // /* TRUE if creature with tag sTarget is of race sRace. Here are the options for sRace: aberration animal beast construct dragon dwarf elemental elf fey goblinoid giant gnome halfelf halfling halforc human humanoid (encompasses goblinoid, monstrous, orc, reptilian) magical_beast monstrous orc ooze outsider reptilian shapechanger undead vermin */ // EPF 6/16/05 #include "ginc_misc" int StartingConditional(string sTarget, string sRace) { sRace = GetStringLowerCase(sRace); object oTarget = GetTarget(sTarget); int nRacialType = GetRacialType(oTarget); int nCheck = -1; if(sRace == "aberration") { nCheck = RACIAL_TYPE_ABERRATION; } else if(sRace == "animal") { nCheck = RACIAL_TYPE_ANIMAL; } else if(sRace == "beast") { nCheck = RACIAL_TYPE_BEAST; } else if(sRace == "construct") { nCheck = RACIAL_TYPE_CONSTRUCT; } else if(sRace == "dragon") { nCheck = RACIAL_TYPE_DRAGON; } else if(sRace == "elemental") { nCheck = RACIAL_TYPE_ELEMENTAL; } else if(sRace == "elf") { nCheck = RACIAL_TYPE_ELF; } else if(sRace == "fey") { nCheck = RACIAL_TYPE_FEY; } else if(sRace == "giant") { nCheck = RACIAL_TYPE_GIANT; } else if(sRace == "gnome") { nCheck = RACIAL_TYPE_GNOME; } else if(sRace == "halfelf") { nCheck = RACIAL_TYPE_HALFELF; } else if(sRace == "halfling") { nCheck = RACIAL_TYPE_HALFLING; } else if(sRace == "halforc") { nCheck = RACIAL_TYPE_HALFORC; } else if(sRace == "human") { nCheck = RACIAL_TYPE_HUMAN; } else if(sRace == "goblinoid") { nCheck = RACIAL_TYPE_HUMANOID_GOBLINOID; } else if(sRace == "monstrous") { nCheck = RACIAL_TYPE_HUMANOID_MONSTROUS; } else if(sRace == "orc") { nCheck = RACIAL_TYPE_HUMANOID_ORC; } else if(sRace == "reptilian") { nCheck = RACIAL_TYPE_HUMANOID_REPTILIAN; } else if(sRace == "magical_beast") { nCheck = RACIAL_TYPE_MAGICAL_BEAST; } else if(sRace == "ooze") { nCheck = RACIAL_TYPE_OOZE; } else if(sRace == "outsider") { nCheck = RACIAL_TYPE_OUTSIDER; } else if(sRace == "shapechanger") { nCheck = RACIAL_TYPE_SHAPECHANGER; } else if(sRace == "undead") { nCheck = RACIAL_TYPE_UNDEAD; } else if(sRace == "vermin") { nCheck = RACIAL_TYPE_VERMIN; } else if(sRace == "humanoid") { return (nRacialType == RACIAL_TYPE_HUMANOID_GOBLINOID || nRacialType == RACIAL_TYPE_HUMANOID_MONSTROUS || nRacialType == RACIAL_TYPE_HUMANOID_ORC || nRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN); } else { PrintString("ERROR in gc_check_race: invalid race parameter specified -- race " + sRace + " does not exist."); } return (nRacialType == nCheck); } // gc_check_race_pc // // returns TRUE if the PC speaker's race corresponds with the race specified. // race can be specified in two ways: by number or by string. The number // is still entered as a string, sRace. // Here are the arguments you can use: // // sRace Alternative // ----- ----------- // dwarf 1 // elf 2 // gnome 3 // halfelf 4 // halfling 5 // halforc 6 // human 7 // outsider 8 // // so gc_check_race_pc("dwarf") and gc_check_race_pc("1") will do the same thing. // You can also check subraces using this function: // (Note: Shield Dwarves, Moon Elves, Lightfoot Halflings, and Rock Gnomes are the common varieties of their // respective races.) // (Note: half-elf, half-orc, and human are considered both races and subraces. The subrace versions should // be prepended with "sr-" as written below, if you intend to check subrace rather than the race.) // // sRace Alternative // ----- ----------- // shielddwarf 11 // moonelf 12 // rockgnome 13 // sr-halfelf 14 // lightfoothalf 15 // sr-halforc 16 // sr-human 17 // golddwarf 18 // duergar 19 // drow 20 // sunelf 21 // woodelf 23 // svirfneblin 24 // stronghearthalf 26 // aasimar 27 // tiefling 28 // civdwarves 41 -- this is all dwarf subraces, save duergar. // civelves 42 -- all elf subraces, save drow and wild. // civhalflings 43 -- all halfling subraces, save ghostwise // // // EPF 6/16/05 // // NOTE: Only subraces supported in NWN2 are implemented here. I just thought I'd leave space for the others in // the event we add them for expansions. int StartingConditional(string sRace) { sRace = GetStringLowerCase(sRace); object oPC = GetPCSpeaker(); int nRacialType = GetSubRace(oPC); int nCheck; int nRace = StringToInt(sRace); int bSubrace = TRUE; //RACES if(sRace == "dwarf" || nRace == 1) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_DWARF; } else if (sRace == "elf" || nRace == 2) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_ELF; } else if (sRace == "gnome" || nRace == 3) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_GNOME; } else if (sRace == "halfelf" || nRace == 4) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_HALFELF; } else if (sRace == "halfling" || nRace == 5) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_HALFLING; } else if (sRace == "halforc" || nRace == 6) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_HALFORC; } else if (sRace == "human" || nRace == 7) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_HUMAN; } else if (sRace == "outsider" || nRace == 8) { nRacialType = GetRacialType(oPC); nCheck = RACIAL_TYPE_OUTSIDER; } //SUBRACES else if(sRace == "shielddwarf" || nRace == 11) { nCheck = RACIAL_SUBTYPE_SHIELD_DWARF; } else if(sRace == "moonelf" || nRace == 12) { nCheck = RACIAL_SUBTYPE_MOON_ELF; } else if(sRace == "rockgnome" || nRace == 13) { nCheck = RACIAL_SUBTYPE_ROCK_GNOME; } else if(sRace == "halfelf" || nRace == 14) { nCheck = RACIAL_SUBTYPE_HALFELF; } else if(GetStringLeft(sRace, 13) == "lightfoothalf" || nRace == 15) { nCheck = RACIAL_SUBTYPE_LIGHTFOOT_HALF; } else if(sRace == "halforc" || nRace == 16) { nCheck = RACIAL_SUBTYPE_HALFORC; } else if(sRace == "human" || nRace == 17) { nCheck = RACIAL_SUBTYPE_HUMAN; } else if(sRace == "golddwarf" || nRace == 18) { nCheck = RACIAL_SUBTYPE_GOLD_DWARF; } else if(sRace == "duergar" || nRace == 19) { nCheck = RACIAL_SUBTYPE_GRAY_DWARF; } else if(sRace == "drow" || nRace == 20) { nCheck = RACIAL_SUBTYPE_DROW; } else if(sRace == "sunelf" || nRace == 21) { nCheck = RACIAL_SUBTYPE_SUN_ELF; } else if(sRace == "woodelf" || nRace == 23) { nCheck = RACIAL_SUBTYPE_WOOD_ELF; } else if(sRace == "svirfneblin" || nRace == 24) { nCheck = RACIAL_SUBTYPE_SVIRFNEBLIN; } else if(GetStringLeft(sRace,16) == "stronghearthalf" || nRace == 26) { nCheck = RACIAL_SUBTYPE_STRONGHEART_HALF; } else if(sRace == "aasimar" || nRace == 27) { nCheck = RACIAL_SUBTYPE_AASIMAR; } else if(sRace == "tiefling" || nRace == 28) { nCheck = RACIAL_SUBTYPE_TIEFLING; } //SETS OF SUBRACES else if(sRace == "civdwarves" || nRace == 41) { return (nRacialType == 1 || nRacialType == 8); } else if(sRace == "civelves" || nRace == 42) { return (nRacialType == 2 || nRacialType == 11 || nRacialType == 13); } else if(sRace == "civhalflings" || nRace == 43) { return (nRacialType == 5 || nRacialType == 16); } return (nRacialType == nCheck); } // gc_check_stats /* This script checks to see if the player (PC_Speaker) has stats above a certain number nStat = The integer of which stat to check for (list boxes will be done later) nVal = The value the stat needs to equal or exceed */ // FAB 10/11 int StartingConditional(int nStat, int nVal) { object oPC = GetPCSpeaker(); int nNewStat; switch ( nStat ) { case 0: // Strength nNewStat = ABILITY_STRENGTH; break; case 1: // Dexterity nNewStat = ABILITY_DEXTERITY; break; case 2: // Constitution nNewStat = ABILITY_CONSTITUTION; break; case 3: // Intelligence nNewStat = ABILITY_INTELLIGENCE; break; case 4: // Wisdom nNewStat = ABILITY_WISDOM; break; case 5: // Charisma nNewStat = ABILITY_CHARISMA; break; } string sSTR = IntToString( nVal ); if ( GetAbilityScore(oPC,nNewStat) >= nVal ) return TRUE; return FALSE; } // gc_comp_remove // // returns TRUE if the companion with tag sCompanion is both in the party and can be removed at this point. // // EPF 6/15/05 // EPF 11/30/05 -- fixing to work with companions #include "ginc_misc" #include "ginc_companion" int StartingConditional(string sCompanion) { object oPC = GetPCSpeaker(); object oComp = GetTarget(sCompanion); string sRoster = GetRosterNameFromObject(oComp); if(!GetIsRosterMemberAvailable(sRoster) && GetIsRosterMemberSelectable(sRoster)) { return TRUE; } return FALSE; } // gc_dead // // Returns true if sCreatureTag is no longer amongst the living (or unliving) // // EPF 4/13/05 int StartingConditional(string sCreatureTag) { return (GetIsDead(GetObjectByTag(sCreatureTag))); } // gc_distance(string sTagA, string sTagB, string sCheck) /* This script compares the distance between objects A and B against sCheck. Parameters: string sTagA = Tag of object A. If blank, use OWNER. string sTagB = Tag of object B. string sCheck = Conditional to compare distance(A,B) to. "<3.0" - distance < 3.0m "=10.0" - distance == 10.0m "!4.0" - distance != 4.0m */ // BMA-OEI 1/14/06 // ChazM 9/20/06 - fixed inc. #include "ginc_var_ops" //#include "ginc_debug" #include "ginc_param_const" int StartingConditional(string sTagA, string sTagB, string sCheck) { object oObjectA = GetTarget(sTagA, TARGET_OWNER); object oObjectB = GetNearestObjectByTag(sTagB, oObjectA); float fDistance = GetDistanceBetween(oObjectA, oObjectB); string sOperator = GetStringLeft(sCheck, 1); float fCompare = StringToFloat(GetStringRight(sCheck, GetStringLength(sCheck) - 1)); return CheckVariableFloat(fDistance, sOperator, fCompare); } // gc_distance_pc(string sTag, string sCheck) /* This script compares the distance between sTag and the nearest PC against sCheck. Parameters: string sTag = Tag of object. If blank, use OWNER. string sCheck = Conditional to compare distance(object,PC) to. "<3.0" - distance < 3.0m "=10.0" - distance == 10.0m "!4.0" - distance != 4.0m */ // BMA-OEI 1/14/06 // ChazM 9/20/06 - fixed inc. #include "nw_i0_plot" #include "ginc_param_const" //#include "ginc_debug" #include "ginc_var_ops" int StartingConditional(string sTag, string sCheck) { object oObject = GetTarget(sTag, TARGET_OWNER); object oPC = GetNearestPC(oObject); float fDistance = GetDistanceBetween(oObject, oPC); string sOperator = GetStringLeft(sCheck, 1); float fCompare = StringToFloat(GetStringRight(sCheck, GetStringLength(sCheck) - 1)); return CheckVariableFloat(fDistance, sOperator, fCompare); } // gc_equipped(string sItem, string sTarget, int bExactMatch) /* Check to see if a given item is equipped by a given creature Parameters: string sItem = The tag, or partial tag of the item. string sTarget = The tag of the creature. If blank, use PCSpeaker. "$PARTY" is a non-standard target constant that will check the entire party. int bExactMatch = If 0, allow sItem to be a tag substring. */ // TDE 3/11/04 // BMA 5/11/05 rewrite to include party, replaced UseName option with FindExact // BMA-OEI 1/11/06 removed default param #include "ginc_misc" #include "ginc_param_const" int StartingConditional(string sItem, string sTarget, int bExactMatch) { object oTarget; if ("$PARTY" == sTarget) { // Check PC Speaker's party for equipped item oTarget = GetPCSpeaker(); return (GetPartyMemberHasEquipped(sItem, oTarget, FALSE, bExactMatch)); } else { // Find target, default PC Speaker to check equipped item oTarget = GetTarget(sTarget, TARGET_PC); return (GetIsItemEquipped(sItem, oTarget, bExactMatch)); } } // gc_false() // Return FALSE // ChazM 5/24 int StartingConditional() { // Debug object oPC = GetPCSpeaker(); DebugPostString(oPC, "gc_false: this is a placeholder script", 50, 50, 5.0f); return (FALSE); } // gc_global_float /* This script checks a local float variable's value sVariable = This is the name of the variable being changed sCheck = This is what you want to see what the local string is set to. Default is an = check, but you can also specify <,>,or ! So an sCheck of "<50" returns TRUE if sVariable is less than 50, an sCheck of "9" or "=9" returns TRUE if sVariable is equal to 9 and an sCheck of "!0" returns TRUE if sVariable is not equal to 0. */ // FAB 10/4 // EPF 4/12/05 changing variable names and implementation, removing superfluous third parameter // adding != functionality, moving common things to ginc_var_check #include "ginc_var_ops" int StartingConditional(string sVariable, string sCheck) { float fCheck; float fValue; string sOperator = GetStringLeft(sCheck, 1); fValue = GetGlobalFloat(sVariable); //first we consider cases where the user specified an operator as the first character //of sCheck if(sOperator == ">" || sOperator == "<" || sOperator == "=" || sOperator == "!") { fCheck = StringToFloat( GetStringRight( sCheck,GetStringLength(sCheck)-1 ) ); } //default case -- no operator specified so use whole string as our check value else { fCheck = StringToFloat(sCheck); sOperator = "="; } return CheckVariableFloat(fValue, sOperator, fCheck); } // gc_global_int /* This script checks a local int variable's value sVariable = This is the name of the variable being changed sCheck = This is what you want to see what the local string is set to. Default is an = check, but you can also specify <,>,or ! So an sCheck of "<50" returns TRUE if sVariable is less than 50, an sCheck of "9" or "=9" returns TRUE if sVariable is equal to 9 and an sCheck of "!0" returns TRUE if sVariable is not equal to 0. */ // FAB 10/4 // EPF 4/12/05 changing variable names and implementation, removing superfluous third parameter // adding != functionality, moving common things to ginc_var_check // ChazM 9/2/05 Updated to use CompareInts() #include "ginc_var_ops" int StartingConditional(string sVariable, string sCheck) { int nValue = GetGlobalInt(sVariable); int iRet = CompareInts(nValue, sCheck); //PrintString ("gc_global_int: nValue = " + IntToString(nValue) + ", sCheck = " + sCheck + " -- return val: " + IntToString(iRet)); return (iRet); } // gc_global_string /* This script checks a local string variable's value sVariable = This is the name of the variable being changed sCheck = This is what you want to see what the local string is set to */ // FAB 10/7 // EPF 4/12/05 spring cleaning int StartingConditional(string sVariable, string sCheck) { if ( GetGlobalString(sVariable) == sCheck ) return TRUE; return FALSE; } // gc_has_feat /* This checks if the creature or player has a given feat sTarg = The creature to check for the feat. If blank, check the PC Speaker nFeat = The number of the feat. See nwscript.nss for a list of feats. bIgnoreUses= Only check if the player has the feat itself, not uses left of the feat */ // TDE 3/7/06 int StartingConditional(string sTarg, int nFeat, int bIgnoreUses) { object oTarg; if ( sTarg == "" ) oTarg = GetFirstPC(); else oTarg = GetObjectByTag(sTarg); if ( GetHasFeat(nFeat, oTarg, bIgnoreUses) ) return TRUE; return FALSE; } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gc_henchman //:: //:: Determines if a creature is a henchman or not. //:: //:: Parameters: //:: - sTarget - The tag of the potential henchman //:: - sMaster - The tag of the potential master. Uses PC Speaker if blank. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 #include "ginc_param_const" #include "ginc_henchman" int StartingConditional(string sTarget, string sMaster) { object oMaster; object oHench=GetTarget(sTarget); if (sMaster=="") oMaster=GetPCSpeaker(); else oMaster=GetTarget(sMaster); if (!GetIsObjectValid(oMaster)) { PrintString("gc_henchman: Could not referance a master In area " + GetName(GetArea(OBJECT_SELF))); return 0; } if (!GetIsObjectValid(oHench)) { PrintString("gc_henchman: Could not find possible henchman: " + sTarget + " In area " + GetName(GetArea(OBJECT_SELF))); return 0; } return GetIsHenchman(oMaster,oHench); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gc_henchman_max //:: //:: Compares the maximum number of allowed Henchmen (as a number) to a criteria (henchmen are not companions). //:: //:: Parameters: string sCheck - works just like gc_local_int //:: it is the operation to check on the value of the variable. //:: //:: Default is ==, but you can also specify <, >, or ! //:: e.g. sCheck of "<50" returns TRUE if sVariable's value is <50 //:: a sCheck of "9" or "=9" returns TRUE if sVariable's value is equal to 9 //:: and a sCheck of "!0" returns TRUE if sVariable's value is not equal to 0. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 - I so ripped this off of gc_local_int. Thanks FAB. I like you. #include "ginc_param_const" #include "ginc_var_ops" //#include "ginc_henchman" int StartingConditional(string sCheck) { int nValue = GetMaxHenchmen(); int iRet = CompareInts(nValue, sCheck); return (iRet); } // gc_is_enemy_near(float fRadius, int bLineOfSight) /* This script checks if an enemy creature is within a given radius from the PC Speaker. Parameters: float fRadius = The radius of the sphere to check within. int bLineOfSight = If =1 check line of sight from PC. */ // TDE 3/9/05 // ChazM 3/10/05 // BMA-OEI 1/11/06 removed default param, change oPC from OBJECT_SELF to PC Speaker // DBR 2/09/06 - Made sure enemy was alive as well int StartingConditional(float fRadius, int bLineOfSight) { object oPC = GetPCSpeaker(); location lPC = GetLocation(oPC); // Search for any creatures that are the enemy of the PC. object oCreature = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lPC, bLineOfSight, OBJECT_TYPE_CREATURE); while(GetIsObjectValid(oCreature) == TRUE) { if (GetIsEnemy(oPC, oCreature) == TRUE) if (GetCurrentHitPoints(oCreature)>0) return (TRUE); oCreature = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lPC, bLineOfSight, OBJECT_TYPE_CREATURE); } // No objects found. return (FALSE); } // gc_is_female /* This checks to see if the PC Speaker is female, returns TRUE if it's a girl */ // FAB 10/11 int StartingConditional() { object oPC = GetPCSpeaker(); if ( GetGender(oPC) == GENDER_FEMALE ) return TRUE; return FALSE; } // gc_is_in_combat // // Returns true if sTarget is in combat // EPF 1/30/06 #include "ginc_misc" int StartingConditional(string sTarget) { return GetIsInCombat(GetTarget(sTarget)); } // gc_is_in_party(string sTarget) /* Check if target henchman is in the party. Parameters: string sTarget = Tag of the henchman to check. If empty, use dialog OWNER. */ // ChazM 4/11 // BMA 4/28/05 added GetTarget() // EPF 11/30/05 fixing to work for Roster companions. // 12/2/05 fixed bug where it didn't check non-PC faction members. // EPF 1/28/06 -- Created a new function in ginc_companions, now this script is just a wrapper. #include "ginc_companion" int StartingConditional(string sTarget) { return IsInParty(sTarget); } // gc_is_male /* This checks to see if the PC Speaker is male, returns TRUE if it's a boy */ // FAB 10/11 int StartingConditional() { object oPC = GetPCSpeaker(); if ( GetGender(oPC) == GENDER_MALE ) return TRUE; return FALSE; } // gc_is_near(string sTag, string sObjTypes, float fRadius, int bLineOfSight) /* This script checks if any object within fRadius radius to the OWNER contains the partial tag sTag. Parameters: string sTag = The tag or partial tag to match to objects nearby. e.g. "guard" will match "guard1", "guard2", "blackguard" string sObjTypes = Filter which types of objects to compare to. C = creature I = item T = trigger D = door A = area of effect W = waypoint P = placeable S = store E = encounter ALL = everything e.g. "CPI" will search only creatures, placeables, and items float fRadius = Radius of sphere to check within. e.g. "20.0f" = 20 meters int bLineOfSight = If =1 check line of sight from OWNER. */ // TDE 3/9/05 // ChazM 3/10/05 // BMA 4/28/05 replaced local function with ginc_param_const include // BMA-OEI 1/11/06 removed default param #include "ginc_param_const" int StartingConditional(string sTag, string sObjTypes, float fRadius, int bLineOfSight) { object oSelf = OBJECT_SELF; location lSelf = GetLocation(OBJECT_SELF); int iObjectFilter = GetObjectTypes(sObjTypes); // Determine objects to filter object oObject = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lSelf, bLineOfSight, iObjectFilter); // Search for any objects whose tags contain sName. while(GetIsObjectValid(oObject) == TRUE) { if (FindSubString(GetTag(oObject), sTag) >= 0 ) return (TRUE); oObject = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lSelf, bLineOfSight, iObjectFilter); } // No objects found. return (FALSE); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gc_is_open.nss //:: //:: Simply calls GetIsOpen() on supplied object tag and returns TRUE/FALSE. //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: Brian Fox //:: Created on: 8/25/05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_param_const" int StartingConditional( string sObjectTag ) { object oObjectToBeChecked = GetTarget( sObjectTag ); return GetIsOpen( oObjectToBeChecked ); } // gc_is_owner /* This script checks if the owner of the dialogue is the given tag sTag = This is the tag of the object you are checking for */ // TDE 2/22/05 // ChazM 3/10/05 int StartingConditional(string sTag) { if (GetTag(OBJECT_SELF) == sTag) return TRUE; return FALSE; } // gc_is_skill_higher /* Checks the speaker's skills. If Skill A is greater than or equal to than Skill B, returns TRUE. Otherwise returns false. if bStrictlyGreaterThan = 1, then we will only return 1 in the case where Skill A is greater than Skill B, and not when they are equal. skill ints 0 APPRAISE 1 BLUFF 2 CONCENTRATION 3 CRAFT ALCHEMY 4 CRAFT ARMOR 5 CRAFT WEAPON 6 DIPLOMACY 7 DISABLE DEVICE 8 DISCIPLINE 9 HEAL 10 HIDE 11 INTIMIDATE 12 LISTEN 13 LORE 14 MOVE SILENTLY 15 OPEN LOCK 16 PARRY 17 PERFORM 18 RIDE 19 SEARCH 20 CRAFT TRAP 21 SLEIGHT OF HAND 22 SPELL CRAFT 23 SPOT 24 SURVIVAL 25 TAUNT 26 TUMBLE 27 USE MAGIC DEVICE */ // EPF 11/14/05 #include "ginc_param_const" int StartingConditional(int nSkillA, int nSkillB, int bStrictlyGreaterThan) { object oPC = GetPCSpeaker(); int nSkillValA = GetSkillConstant(nSkillA); int nSkillValB = GetSkillConstant(nSkillB); if (!bStrictlyGreaterThan && GetSkillRank(nSkillValA, oPC) >= GetSkillRank(nSkillValB, oPC)) { return TRUE; } else if (bStrictlyGreaterThan && GetSkillRank(nSkillValA, oPC) > GetSkillRank(nSkillValB, oPC)) { return TRUE; } else { return FALSE; } } // gc_item_count(string sItemTag, string sCheck, int bPCOnly) /* Compares the number of items with tag sItemTag the speaker/party possesses to condition sCheck. Parameters: string sItemTag = Tag of the item to count. string sCheck = Condition and value to check, for example: "<5" Less than 5 ">1" Greater than 1 "=9" Equal to 9 "!0" Not equal to 0 int bPCOnly = If =0 then check party's inventory, else check speaker inventory only */ // BMA 5/9/05 // BMA-OEI 1/11/06 removed default param, replaced henchmen w/ faction #include "ginc_var_ops" #include "nw_i0_plot" int StartingConditional(string sItemTag, string sCheck, int bPCOnly) { object oPC = GetPCSpeaker(); object oMember; int nItems = 0; if (bPCOnly == 0) { nItems = GetNumItems(oPC, sItemTag); } else { oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember)) { nItems = nItems + GetNumItems(oMember, sItemTag); oMember = GetNextFactionMember(oPC, FALSE); } } return CompareInts(nItems, sCheck); } // gc_journal_entry /* This script compares the state of specified journal quest to a check value. sQuestTag - tag of the quest to examine on the PC sCheck - conditional to check against. This param works the same as it does in gc_local_int. */ // ChazM 4/12/05 #include "ginc_var_ops" // Will return 0 if no quest. int StartingConditional(string sQuestTag, string sCheck) { object oPC = GetPCSpeaker(); int iQuestEntry = GetLocalInt(oPC, "NW_JOURNAL_ENTRY" + sQuestTag); return (CompareInts(iQuestEntry, sCheck)); } // gc_local_float(string sVariable, string sCheck, string sTarget) /* This script checks a local float variable's value. Parameters: string sVariable = This is the name of the variable. string sCheck = This is the operation to compare local float to. e.g. If sCheck = "<10.0" then return TRUE if sVariable < 10.0 If sCheck = "9.0" or "=9.0" then return TRUE OR FALSE if sVariable is equal to 9.0. We cannot guarentee float accuracy, so == comparisons will generally fail. string sTarget = Identifier or tag of the Target. If blank then use OWNER. */ // FAB 10/4 // EPF 4/12/05 changing variable names and implementation, // adding != functionality, moving common things to ginc_var_check // BMA 4/27/05 add GetTarget(), logic fix, description update // BMA 7/19/05 added object invalid printstring #include "ginc_param_const" #include "ginc_var_ops" int StartingConditional(string sVariable, string sCheck, string sTarget) { object oTarget = GetTarget(sTarget, TARGET_OBJECT_SELF); if (GetIsObjectValid(oTarget) == FALSE) PrintString("gc_local_float: " + sTarget + " is invalid"); float fValue = GetLocalFloat(oTarget, sVariable); float fCheck; string sOperator = GetStringLeft(sCheck, 1); if(sOperator == ">" || sOperator == "<" || sOperator == "=" || sOperator == "!") { fCheck = StringToFloat( GetStringRight( sCheck,GetStringLength(sCheck)-1 ) ); } else { fCheck = StringToFloat(sCheck); sOperator = "="; } return CheckVariableFloat(fValue, sOperator, fCheck); } // gc_local_int(string sVariable, string sCheck, string sTarget) /* This script checks a local int variable's value. Parameters: string sVariable = The name of the variable string sCheck = The operation to check on the value of the variable. Default is ==, but you can also specify <, >, or ! e.g. sCheck of "<50" returns TRUE if sVariable's value is <50 a sCheck of "9" or "=9" returns TRUE if sVariable's value is equal to 9 and a sCheck of "!0" returns TRUE if sVariable's value is not equal to 0. string sTarget = Tag or identifier of Target. If blank then use dialog OWNER. */ // FAB 10/4 // EPF 4/12/05 changing variable names and implementation, // adding != functionality, moving common things to ginc_var_check // ChazM 4/15 change implementation, added PrintString // BMA 4/27/05 new description, added GetTarget() // BMA 7/19/05 added object invalid printstring #include "ginc_var_ops" #include "ginc_param_const" int StartingConditional(string sVariable, string sCheck, string sTarget) { object oTarg = GetTarget(sTarget, TARGET_OBJECT_SELF); if (GetIsObjectValid(oTarg) == FALSE) PrintString("gc_local_int: " + sTarget + " is invalid"); int nValue = GetLocalInt(oTarg, sVariable); int iRet = CompareInts(nValue, sCheck); PrintString ("gc_local_int: nValue = " + IntToString(nValue) + ", sCheck = " + sCheck + " -- return val: " + IntToString(iRet)); return (iRet); } // gc_local_string(string sVariable, string sCheck, string sTarget) /* This script checks a local string variable's value. Parameters: string sVariable = This is the name of the variable checked. string sCheck = This is the string to compare equality against. string sTarget = This is the tag or identifier of the Target. If blank then use OWNER */ // FAB 10/4 // EPF 4/12/05 variable name changes, some minor cleaning // BMA 4/27/05 added GetTarget(), new description // BMA 7/19/05 added object invalid printstring // BMA-OEI 7/28/05 - added debug printstring #include "ginc_param_const" int StartingConditional(string sVariable, string sCheck, string sTarget) { object oTarget = GetTarget(sTarget, TARGET_OWNER); string sValue = GetLocalString(oTarget, sVariable); PrintString("gc_local_string: Object '" + GetName(oTarget) + "' variable '" + sVariable + "' = '" + sValue + "' compare to '" + sCheck + "'"); if (sValue == sCheck) { return TRUE; } else { return FALSE; } } // gc_module( string sTag ) /* Compare sTag to current module's tag. */ // BMA-OEI 5/15/06 int StartingConditional( string sTag ) { object oModule = GetModule(); return ( GetTag( oModule ) == sTag ); } // gc_node /* Used on nodes of a dialog to specify it's index. iNodeIndex - This Node's index (for use w/ gtr_speak_node) */ // ChazM 4/6/05 // ChazM 5/25/05 - added check for OnceOnly flag int StartingConditional (int iNodeIndex) { // these 2 vars are set on creature by gtr_speak_node int iSavedNodeIndex = GetLocalInt(OBJECT_SELF, "sn_NodeIndex"); int iOnceOnly = GetLocalInt(OBJECT_SELF, "sn_OnceOnly"); // signal that we should clear node if true //PrintString ("gc_node: iSavedNodeIndex = " + IntToString(iSavedNodeIndex)); //PrintString ("gc_node: iNodeIndex = " + IntToString(iNodeIndex)); if (iSavedNodeIndex == iNodeIndex) { if (iOnceOnly) SetLocalInt(OBJECT_SELF, "sn_NodeIndex", 0); return TRUE; } else return FALSE; } // gc_num_comps (string sCheck) /* This script checks number of roster companions the player has. Parameters: string sCheck = The operation to check on the value of the variable. Default is ==, but you can also specify <, >, or ! e.g. sCheck of "<50" returns TRUE if sVariable's value is <50 a sCheck of "9" or "=9" returns TRUE if sVariable's value is equal to 9 and a sCheck of "!0" returns TRUE if sVariable's value is not equal to 0. */ // ChazM 7/14/05 // 12/5/05 - BDF: updated for compatibility with new roster companions #include "ginc_var_ops" int StartingConditional( string sCheck ) { // return number of henchman, -1 if a problem occurs. object oPC = GetPCSpeaker(); object oFactionMember = GetFirstFactionMember( oPC, FALSE ); int nNumCompanions = 0; while ( GetIsObjectValid(oFactionMember) ) { if ( GetIsRosterMember(oFactionMember) ) { nNumCompanions++; } oFactionMember = GetNextFactionMember( oPC, FALSE ); } int iRet = CompareInts( nNumCompanions, sCheck ); return (iRet); } // gc_num_pcs (string sCheck) /* This script checks number of PCs in the current game. Parameters: string sCheck = The operation to compare to the number of PCs(NumPC). Default is "=", but you can also specify "<", ">", or "!" e.g. sCheck of "<3" returns TRUE if NumPC is less than 3, sCheck of "2" or "=2" returns TRUE if NumPC is equal to 2, and sCheck of "!1" returns TRUE if NumPC is not equal to 1. */ // BMA-OEI 11/29/05 #include "ginc_var_ops" #include "ginc_debug" int StartingConditional(string sCheck) { object oPC = GetFirstPC(); // get number of PCs int nNumPCs = 0; while (GetIsObjectValid(oPC) == TRUE) { nNumPCs = nNumPCs + 1; oPC = GetNextPC(); } return ( CompareInts(nNumPCs, sCheck) ); } // gc_obj_valid(string sTag, int bAreaOnly) /* Determines if object is valid (e.g. exists, != OBJECT_INVALID). GetNearest may fail in case of searching the OWNER's tag. Parameters: string sTag = The tag of the object to search for. int bAreaOnly = If =0 search entire module; otherwise search OWNER's area only. */ // BMA 4/20/05 // BMA-OEI 8/26/05 swapped getobject/getnearest, changed parameters // BMA-OEI 1/11/05 removed default params int StartingConditional(string sTag, int bAreaOnly) { object oObject; if (bAreaOnly == 0) { // Search module oObject = GetObjectByTag(sTag); } else { // Search area from owner only oObject = GetNearestObjectByTag(sTag); } return GetIsObjectValid(oObject); } // gc_rand_1of /* Used to randomly pick a dialog response. Use paramaters 2 through X for each entry after the first, decementing by 1 for each branch going down. Example: 3 entries would have the following conditionals: gc_rand_1of(3) gc_rand_1of(2) The final entry doesn't need a check since it is a certainty. */ // ChazM 3/10/05 int StartingConditional(int iMax) { int iResult; iResult = Random(iMax) == 1; return iResult; } // gc_reputation /* This checks the reputation of the speaking player nRepLevel = Checks how noble or ignoble the player's rep is from +4 (Idolized) to -4 (Vilified) nRepNumber = See if it is over a specific number value (overrides previous int) */ // FAB 10/12/04 int StartingConditional(int nRepLevel, int nRepNumber) { object oPC = GetPCSpeaker(); if ( nRepNumber != 0 ) { if ( GetLocalInt(oPC,"Player's Reputation") >= nRepNumber ) return TRUE; else return FALSE; } int nRepCurrent; // This is the reputation level of the PC right now int nRepValue; // The straight Reputation Score nRepValue = GetLocalInt( oPC,"Player's Reputation" ); if ( nRepCurrent <= -110 ) nRepLevel = -4; else if ( nRepCurrent <= -80 ) nRepLevel = -3; else if ( nRepCurrent <= -50 ) nRepLevel = -2; else if ( nRepCurrent <= -25 ) nRepLevel = -1; else if ( nRepCurrent <= 24 ) nRepLevel = 0; else if ( nRepCurrent <= 49 ) nRepLevel = 1; else if ( nRepCurrent <= 79 ) nRepLevel = 2; else if ( nRepCurrent <= 109 ) nRepLevel = 3; else nRepLevel = 4; if ( nRepLevel >= nRepCurrent ) return TRUE; return FALSE; } //gc_roster_available /* //RWT-OEI 09/14/05 //Returns TRUE if the member is available to be added to a party at this //time. If the member is currently claimed by another party, it will //not be available. If the member is set unselectable, it will //not be available. int GetIsRosterMemberAvailable( string sRosterName ); */ // ChazM 12/2/05 int StartingConditional( string sRosterName) { int bResult = GetIsRosterMemberAvailable(sRosterName); return (bResult); } // gc_roster_campaignnpc( string sRosterName ) /* Returns CampaignNPC flag T/F of roster member sRosterName. Returns FALSE if unable to find sRosterName in roster table. //RWT-OEI 09/29/05 //This function returns whether or not a valid roster member is set //as a Campaign NPC. See description of SetIsRosterMemberCampaignNPC //for details on Campaign NPCs. //Returns true or false, depending. False returned if unable to find the //roster member int GetIsRosterMemberCampaignNPC( string sRosterName ); */ // BMA-OEI 4/01/06 int StartingConditional( string sRosterName ) { int bResult = GetIsRosterMemberCampaignNPC( sRosterName ); return ( bResult ); } //gc_roster_selectable /* //RWT-OEI 09/14/05 //Returns TRUE if the member is selectable. This is different than //available because it is possible for the NPC to -not- be in another //party but still set to be not selectable (Due to plot reasons, etc.) int GetIsRosterMemberSelectable( string sRosterName ); */ // ChazM 12/2/05 int StartingConditional( string sRosterName) { int bResult = GetIsRosterMemberSelectable(sRosterName); return (bResult); } // gc_singleplayer () /* Returns TRUE if this is a single player only game, otherwise returns FALSE. */ // BMA-OEI 11/29/05 int StartingConditional() { return ( GetIsSinglePlayer() ); } // gc_skill_dc(int nSkill, int nDC) /* Determine if PC Speaker's skill roll is successful. Parameters: int nSkill = skill int to check int nDC = difficulty class to beat Remarks: skill ints 0 APPRAISE 1 BLUFF 2 CONCENTRATION 3 CRAFT ALCHEMY 4 CRAFT ARMOR 5 CRAFT WEAPON 6 DIPLOMACY 7 DISABLE DEVICE 8 DISCIPLINE 9 HEAL 10 HIDE 11 INTIMIDATE 12 LISTEN 13 LORE 14 MOVE SILENTLY 15 OPEN LOCK 16 PARRY 17 PERFORM 18 RIDE 19 SEARCH 20 CRAFT TRAP 21 SLEIGHT OF HAND 22 SPELL CRAFT 23 SPOT 24 SURVIVAL 25 TAUNT 26 TUMBLE 27 USE MAGIC DEVICE */ // BMA-OEI 9/02/05 #include "ginc_param_const" int StartingConditional(int nSkill, int nDC) { object oPC = GetPCSpeaker(); int nSkillVal = GetSkillConstant(nSkill); if (GetIsSkillSuccessful(oPC, nSkillVal, nDC) == TRUE) { return TRUE; } else { return FALSE; } } // gc_skill_rank(int nSkill, int nRank) /* Determine if PC Speaker has sufficient rank in a particular skill. Parameters: int nSkill = skill int to check int nRank = minimum rank to return TRUE Remarks: skill ints 0 APPRAISE 1 BLUFF 2 CONCENTRATION 3 CRAFT ALCHEMY 4 CRAFT ARMOR 5 CRAFT WEAPON 6 DIPLOMACY 7 DISABLE DEVICE 8 DISCIPLINE 9 HEAL 10 HIDE 11 INTIMIDATE 12 LISTEN 13 LORE 14 MOVE SILENTLY 15 OPEN LOCK 16 PARRY 17 PERFORM 18 RIDE 19 SEARCH 20 CRAFT TRAP 21 SLEIGHT OF HAND 22 SPELL CRAFT 23 SPOT 24 SURVIVAL 25 TAUNT 26 TUMBLE 27 USE MAGIC DEVICE */ // BMA-OEI 9/02/05 #include "ginc_param_const" int StartingConditional(int nSkill, int nRank) { object oPC = GetPCSpeaker(); int nSkillVal = GetSkillConstant(nSkill); if (GetSkillRank(nSkillVal, oPC) >= nRank) { return TRUE; } else { return FALSE; } } // gc_talkto(string sTarget) /* This checks to see if you have not talked to this person before. See ga_talkto.nss. Parameters: string sTarget = Target of the NPC. If blank, use dialog OWNER. */ // FAB 9/30 // BMA 4/28/05 added GetTarget() #include "ginc_param_const" int StartingConditional(string sTarget) { object oTarget = GetTarget(sTarget, TARGET_OWNER); if (GetLocalInt(oTarget, "TalkedTo") != 1) { return TRUE; } else { return FALSE; } } // gc_true() // Return TRUE // BMA-OEI 8/02/05 int StartingConditional() { // Debug object oPC = GetPCSpeaker(); DebugPostString(oPC, "gc_true: this is a placeholder script", 50, 50, 5.0f); return (TRUE); } Global Door // gd_close_op /* closes door after someone opens a door goes on the onOpen event of a door. */ // Chazm 3/8/05 void main() { DelayCommand(9.0, ActionCloseDoor(OBJECT_SELF)); } // gdm_copy_first /* copy the first item in player's inventory. This script for use in normal conversation */ // ChazM 12/30/05 void main() { object oPC = GetPCSpeaker(); object oItem = GetFirstItemInInventory(oPC); if (!GetIsObjectValid(oItem)) { SpeakString("Item not found in inventory."); return; } object oNewItem = CopyItem(oItem, oPC, TRUE); if (!GetIsObjectValid(oNewItem)) { SpeakString("Item failed to copy."); return; } } Global Dungeon Master // gdm_getparam2 /* Stops DM from listening for param. This script for use in normal conversation */ // ChazM 11/13/05 void main() { SetListening(OBJECT_SELF, FALSE); SetCustomToken(99, GetLocalString(GetPCSpeaker(), "dm_param")); } // gdm_getparam /* Sets DM up to get a param. This script for use in normal conversation */ // ChazM 11/13/05 void main() { SetListening(OBJECT_SELF, TRUE); } // gdm_henchinv /* open inventory of henchman. This script for use in normal conversation */ // ChazM 11/13/05 #include "gdm_inc" /* int GetIntParam() { int iParam = StringToInt(GetLocalString(GetPCSpeaker(), "dm_param")); return (iParam); } */ void main() { int iHench = GetIntParam(); object oPC = GetPCSpeaker(); if (iHench < 1) iHench = 1; OpenInventory(GetHenchman(oPC, iHench), oPC); } // gdm_inc /* include file for dm convo. */ // ChazM 11/13/05 int GetIntParam() { int iParam = StringToInt(GetLocalString(GetPCSpeaker(), "dm_param")); return (iParam); } string GetStringParam() { string sParam = GetLocalString(GetPCSpeaker(), "dm_param"); return (sParam); } // gdm_journal /* update journal. overrides normal restriciton preventing lower entry ids than current to be set. This script for use in normal conversation */ // ChazM 3/24/06 #include "gdm_inc" #include "X0_I0_STRINGLIB" #include "ginc_debug" void main() { string sInput = GetStringParam(); string sCategoryTag = GetTokenByPosition(sInput, ",", 0); int nEntryID = StringToInt(GetTokenByPosition(sInput, ",", 1)); PrettyDebug("sCategoryTag = " + sCategoryTag); PrettyDebug("nEntryID = " + IntToString(nEntryID)); object oPC = GetPCSpeaker(); AddJournalQuestEntry(sCategoryTag, nEntryID, oPC, TRUE, FALSE, TRUE); } // gdm_leave /* open inventory of henchman. This script for use in normal conversation */ // ChazM 11/13/05 void main() { DestroyObject(OBJECT_SELF, 0.5f); } // gdm_load_area /* load specified module. This script for use in normal conversation */ // ChazM 2/24/06 /* int OBJECT_TYPE_CREATURE = 1; int OBJECT_TYPE_ITEM = 2; int OBJECT_TYPE_TRIGGER = 4; int OBJECT_TYPE_DOOR = 8; int OBJECT_TYPE_AREA_OF_EFFECT = 16; int OBJECT_TYPE_WAYPOINT = 32; int OBJECT_TYPE_PLACEABLE = 64; int OBJECT_TYPE_STORE = 128; int OBJECT_TYPE_ENCOUNTER = 256; int OBJECT_TYPE_LIGHT = 512; int OBJECT_TYPE_PLACED_EFFECT = 1024; int OBJECT_TYPE_ALL = 32767; int OBJECT_TYPE_INVALID = 32767; area object appear to return type 0. */ //#include "gdm_inc" #include "ginc_debug" #include "ginc_param_const" object GetFirstWPInArea(object oArea) { // Loop through objects in oArea until we find a waypoint object oObject = GetFirstObjectInArea(oArea); while(GetIsObjectValid(oObject)) { // Destroy any objects tagged "DESTROY" if(GetObjectType(oObject) == OBJECT_TYPE_WAYPOINT) { return(oObject); } oObject = GetNextObjectInArea(oArea); } return (OBJECT_INVALID); } void main() { string sTag = GetLocalString(GetPCSpeaker(), "dm_param"); object oPC = GetPCSpeaker(); object oObject = GetTarget(sTag); /* if (!GetIsObjectValid(oArea)) { PrettyDebug("Target not a valid area."); return; } */ int iType = GetObjectType(oObject); PrettyDebug("Tagged object is Type: " + IntToString(iType)); if (iType == 0) // areas are type 0 { object oWP = GetFirstWPInArea(oObject); if (!GetIsObjectValid(oWP)) { PrettyDebug("No waypoints found in target area."); return; } oObject = oWP; } PrettyDebug("Jumping to object " + GetName(oObject) + " - Tag: " + GetTag(oObject) + " which is type " + IntToString(GetObjectType(oObject))); AssignCommand(oPC, ActionJumpToObject(oObject)); } // gdm_load_module /* load specified module. This script for use in normal conversation */ // ChazM 2/24/06 #include "gdm_inc" void main() { string sModule = GetStringParam(); object oPC = GetPCSpeaker(); LoadNewModule(sModule); } // gdm_makeitem /* create item from specified blueprint. This script for use in normal conversation */ // ChazM 11/13/05 #include "gdm_inc" void main() { string sResRef = GetStringParam(); object oPC = GetPCSpeaker(); object oItem = CreateItemOnObject(sResRef, oPC); if (!GetIsObjectValid(oItem)) SpeakString("Item blueprint not found."); } // gdm_maxhench /* Set Max Num Henchmen. This script for use in normal conversation */ // ChazM 11/13/05 #include "gdm_inc" void main() { int iHench = GetIntParam(); //object oPC = GetPCSpeaker(); if (iHench < 0) iHench = 0; SetMaxHenchmen(iHench); } // gdm_store /* open store - attempt to create one if not found. This script for use in normal conversation */ // ChazM 11/13/05 #include "gdm_inc" void main() { string sStore = GetStringParam(); object oPC = GetPCSpeaker(); object oStore = GetObjectByTag(sStore); if (!GetIsObjectValid(oStore)) { oStore = CreateObject(OBJECT_TYPE_STORE, sStore, GetLocation(OBJECT_SELF)); } OpenStore(oStore, oPC); } Global Group // gg_death_custom_script /* Executes a custom script on the module when a group dies. */ // ChazM 4/19/06 // BMA-OEI 5/23/06 -- Updated w/ new group functions, moved ExecuteScript() to module #include "ginc_group" void main() { string sGroupName = GetGroupName( OBJECT_SELF ); // Update number of sGroupName members killed IncGroupNumKilled( sGroupName ); // If all group members are dead or invalid if ( GetIsGroupValid( sGroupName, TRUE ) == FALSE ) { object oModule = GetModule(); string sCustomScript = GetGroupString( sGroupName, "CustomScript" ); AssignCommand( oModule, ExecuteScript( sCustomScript, oModule ) ); } } // gg_death_journal /* GroupOnDeath handler to advance journal state of first PC. Checks group local variables sQuestTag, nEntry, and bOverride */ // EPF 12/3/05 // BMA-OEI 5/23/06 -- Updated w/ new group functions #include "ginc_group" void main() { string sGroupName = GetGroupName( OBJECT_SELF ); // Update number of sGroupName members killed IncGroupNumKilled( sGroupName ); // If all group members are dead or invalid if ( GetIsGroupValid( sGroupName, TRUE ) == FALSE ) { string sQuest = GetGroupString( sGroupName, "sQuestTag" ); int nEntry = GetGroupInt( sGroupName, "nEntry" ); int bOverride = GetGroupInt( sGroupName, "bOverride" ); AddJournalQuestEntry( sQuest, nEntry, GetFirstPC(), TRUE, FALSE, bOverride ); } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gg_death_l_var.nss //:: //:: This is the DeathScript for GroupOnDeathSetLocal (int, float, string). //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: Brian Fox //:: Created on: 9/2/05 //:: //:://///////////////////////////////////////////////////////////////////////// // BMA-OEI 5/23/06 -- Updated w/ new group functions #include "ginc_group" void main() { string sGroupName = GetGroupName( OBJECT_SELF ); // Update number of sGroupName members killed IncGroupNumKilled( sGroupName ); // If all group members are dead or invalid if ( GetIsGroupValid( sGroupName, TRUE ) == FALSE ) { object oTarget = GetGroupObject( sGroupName, "TargetObject" ); string sVarName = GetGroupString( sGroupName, "VarName" ); switch ( GetGroupInt( sGroupName, "VarType" ) ) { case TYPE_INT: SetLocalInt( oTarget, sVarName, GetGroupInt( sGroupName, "VarValue" )); break; case TYPE_FLOAT: SetLocalFloat( oTarget, sVarName, GetGroupFloat( sGroupName, "VarValue" )); break; case TYPE_STRING: SetLocalString( oTarget, sVarName, GetGroupString( sGroupName, "VarValue" )); break; } } } // gg_death_talk.nss /* Group DeathScript. Assigned using GroupOnDeathBeginConversation(). Creates an IPoint Speaker when all group members have been killed to begin a conversation. */ // ChazM 6/16/05 // ChazM 6/20/05 - changed string to constant // ChazM 7/7/05 - func name fix // ChazM 7/28/05 - Start conversation now ignores distance so we can be assured it starts. // ChazM 12/12/05 - clear PC actions // BMA-OEI 1/13/06 - update for GetGroupIsValid, reset PC control, rez party // BMA-OEI 1/23/06 - update to use IPSpeaker heartbeat // BMA-OEI 2/8/06 - Updated ResetIPSpeaker to delete after use, fade out // DBR 2/09/06 - bFadeOut being put in wrong spot // BMA-OEI 2/14/06 - Delays and Fades do more bad than good :( // BMA-OEI 3/6/06 - revised comments // BMA-OEI 5/23/06 - Updated w/ new group functions //#include "ginc_cutscene" //#include "ginc_debug" #include "ginc_group" #include "ginc_ipspeaker" //#include "ginc_misc" //#include "nw_i0_plot" void main() { string sGroupName = GetGroupName( OBJECT_SELF ); // Update number of sGroupName members killed //PrettyMessage( "gg_death_talk: " + sGroupName + " death count = " + IntToString( IncGroupNumKilled( sGroupName ) ) ); // If all group members are dead or invalid if ( GetIsGroupValid( sGroupName, TRUE ) == FALSE ) { string sTalkerTag = GetGroupString( sGroupName, "TalkerTag" ); string sConversation = GetGroupString( sGroupName, "Conversation" ); //PrettyDebug( "gg_death_talk: " + sGroupName + " wiped. Start IPSpeaker conversation: " + sConversation ); // Spawn IPoint Speaker and setup one-shot pending conversation CreateIPSpeaker( sTalkerTag, sConversation, GetLocation( OBJECT_SELF ), 1.75f ); } } Global Include // ginc_actions /* various encapsulated action funtions Main characteristic of action functions is that they are applied to the object that runs them, a target is not supplied as a parameter. */ // ChazM 3/9/05 // ChazM 5/5/05 added constants and prototypes section, added ActionOrientTOTag(), ActionMoveToTag(), ActionTurnHostile(), FindDestinationByTag() // ChazM 5/12/05 added ActionPlayAnimationUncommandable() and ActionPrintString() // ChazM 5/26/05 added ginc_group include // ChazM 5/27/05 added ActionFireEvent(), IncrementGlobalInt(), NoInterrupt(), and CheckOrderComplete() // ChazM 5/31/05 modified IncrementGlobalInt() // ChazM 6/6/05 no longer includes ginc_group // ChazM 6/14/05 added ActionForceMoveToTag() // ChazM 6/28/05 added ActionForceExit() // ChazM 7/29/05 added ActionStartConversationNode() // ChazM 9/21/05 added ActionJumpToTag() // EPF 11/15/05 -- StandardAttack() now changes the Attacker to be hostile instead of a temporary enemy, since personal rep is out. // ChazM 11/29/05 added SetNode() and ActionSpeakNode(), removed ActionStartConversationNode() // DBR 12/16/05 - Added parameter to NoInterrupt() for immediate focused action. // ChazM 9/18/06 - Updated ActionForceExit(), added RemoveCreature() // ChazM 9/18/06 - changed RemoveCreature() to ActionRemoveMyself()/RemoveMyself() // ChazM 9/21/06 - removed nw_i0_generic, added ExecuteDCR(), modified ActionTurnHostile(), StandardAttack() //#include "nw_i0_generic" //void main(){} /////////////////////////////////////////////// // constants /////////////////////////////////////////////// const int ORIENT_FACE_TARGET = 1; const int ORIENT_FACE_SAME_AS_TARGET = 2; /////////////////////////////////////////////// // Prototypes /////////////////////////////////////////////// void ActionForceMoveToTag(string sTag ,int bRun=FALSE, float fRange = 1.0f, float fTimeout = 30.0f); void ActionMoveToTag(string sTag ,int bRun=FALSE, float fRange = 1.0f); void ActionJumpToTag(string sTag, int bWalkStraightLineToPoint=FALSE); void ActionOrientToObject(object oTarget, int iOrientation = ORIENT_FACE_TARGET); void ActionOrientToTag(string sTag, int iOrientation = ORIENT_FACE_TARGET); void ActionCreateObject (int nObjectType, string sTemplate, location lLocation, int bUseAppearAnimation=FALSE, string sNewTag=""); void ExecuteDCR(object oExecutor = OBJECT_SELF); void ActionTurnHostile(); void StandardAttack(object oAttacker, object oTarget); void ActionPlayAnimationUncommandable(int nAnimation, float fSpeed=1.0, float fDurationSeconds=0.0); void ActionPrintString(string sMsg); void ActionFireEvent(string sTag, int iEventNum); int IncrementGlobalInt(string sVarName); void NoInterrupt (float fTimeOut = 180.0f, int bFocusNow=0); void ActionRemoveMyself(); void ActionForceExit(string sExitTag = "WP_EXIT", int bRun=FALSE); //void ActionStartConversationNode(object oPC, string sConversation, int iNodeIndex); void ActionSpeakNode(int iNodeIndex, string sDialog = "", object oObjectToConverseWith = OBJECT_SELF, int iOnceOnly = TRUE); // private prototypes object FindDestinationByTag(string sTarget); void CheckOrderComplete(int iOrderNum); void RemoveMyself(); /////////////////////////////////////////////// // Function Definitions /////////////////////////////////////////////// void ActionForceMoveToTag(string sTag ,int bRun=FALSE, float fRange = 1.0f, float fTimeout = 30.0f) { object oWayPoint = GetObjectByTag(sTag); ActionForceMoveToObject(oWayPoint, bRun, fRange, fTimeout); } void ActionMoveToTag(string sTag ,int bRun=FALSE, float fRange = 1.0f) { object oWayPoint = GetObjectByTag(sTag); ActionMoveToObject(oWayPoint, bRun, fRange); } void ActionJumpToTag(string sTag, int bWalkStraightLineToPoint=FALSE) { ActionJumpToObject(GetObjectByTag(sTag), bWalkStraightLineToPoint); } // Orient to a target object void ActionOrientToObject(object oTarget, int iOrientation = ORIENT_FACE_TARGET) { switch (iOrientation){ case ORIENT_FACE_TARGET: //ActionDoCommand(SetFacingPoint( GetPositionFromLocation(GetLocation(oTarget)))); ActionDoCommand(SetFacingPoint(GetPosition(oTarget))); break; case ORIENT_FACE_SAME_AS_TARGET: ActionDoCommand(SetFacing(GetFacing(oTarget))); break; } ActionWait(0.5f); // need time to change facing } // Orient to an object with sTag void ActionOrientToTag(string sTag, int iOrientation = ORIENT_FACE_TARGET) { object oTarget = FindDestinationByTag(sTag); ActionOrientToObject(oTarget, iOrientation); } // wrapper for CreateObject that returns a void (so it can be assigned as an action) void ActionCreateObject (int nObjectType, string sTemplate, location lLocation, int bUseAppearAnimation=FALSE, string sNewTag="") { CreateObject(nObjectType, sTemplate, lLocation, bUseAppearAnimation, sNewTag); } void ExecuteDCR(object oExecutor = OBJECT_SELF) { //DetermineCombatRound(); ExecuteScript("gr_dcr", oExecutor); } // change to hostile faciton and look for something to attack. void ActionTurnHostile() { ChangeToStandardFaction(OBJECT_SELF, STANDARD_FACTION_HOSTILE); //DetermineCombatRound(); ExecuteDCR(OBJECT_SELF); } // void StandardAttack(object oAttacker, object oTarget) { PrintString ("Setting " + GetName(oAttacker) + " to attack " + GetName(oTarget)); // make sure action queue is empty / conversation is finished AssignCommand(oAttacker, ClearAllActions(TRUE)); // make target enemy of attacker ChangeToStandardFaction(oAttacker, STANDARD_FACTION_HOSTILE); // tell attacker to initiate combat - attacker will determine best who to attack and how. //AssignCommand(oAttacker, DetermineCombatRound()); AssignCommand(oAttacker, ExecuteDCR(oAttacker)); // This is here only temporarily to further push an attack because above not fully working currently AssignCommand(oAttacker, ActionAttack(oTarget)); } // internal funcs // look for waypoint w/ Tag. If not found then look for an object in the area, and finally, look for any obj object FindDestinationByTag(string sTarget) { object oTarget = GetWaypointByTag(sTarget); if (!GetIsObjectValid(oTarget)) { oTarget = GetNearestObjectByTag(sTarget); // search area if (!GetIsObjectValid(oTarget)) { oTarget = GetObjectByTag(sTarget); // search module } } return (oTarget); } // When ActionPlayAnimation() (and likely several others) is active, GetCurrentAction() returns ACTION_INVALID // This could be misinterpreted as having an empty queue. To avoid having the queue cleared in this case, use this function. // Be mindful of the queue being unmodifiable while this is active. void ActionPlayAnimationUncommandable(int nAnimation, float fSpeed=1.0, float fDurationSeconds=0.0) { ActionDoCommand(SetCommandable(FALSE)); ActionPlayAnimation(nAnimation, fSpeed, fDurationSeconds); ActionDoCommand(SetCommandable(TRUE)); } // For adding PrintString() to an action queue. void ActionPrintString(string sMsg) { ActionDoCommand(PrintString(sMsg)); } //This is only for user defined event numbers. void ActionFireEvent(string sTag, int iEventNum) { ActionDoCommand(SignalEvent(GetObjectByTag(sTag), EventUserDefined(iEventNum))); } // Return a unique order number int IncrementGlobalInt(string sVarName) { int iValue = GetGlobalInt(sVarName) + 1; SetGlobalInt(sVarName, iValue); return (iValue); } // more actions can not be put on queue after this call until // all actions have completed /* Example of how this function might be used. ActionPlayAnimation (ANIMATION_FIREFORGET_GREETING); ActionSpeakString("Skee!"); ActionMoveToWP("xWP_Shelk_01"); // walk to WP NoInterrupt(); // commands after the NoInterrupt will occur after commandable is turned on and could be interrupted. ActionSpeakString("Skee!"); */ //new bFocusNow param prevents the 0.2 second delay before SetCommandable(FALSE), but doesn't allow further // interuptable actions to be queued after the non-interuptable ones. void NoInterrupt (float fTimeOut = 180.0f, int bFocusNow=0) { //int iOrderNum = Random(10000); int iOrderNum = IncrementGlobalInt("N2_CurrentOrderNum"); SetLocalInt(OBJECT_SELF, "N2_ActionOrderNumber", iOrderNum); ActionDoCommand(SetCommandable(TRUE)); ActionDoCommand(SetLocalInt(OBJECT_SELF, "N2_ActionOrderNumber", 0)); if (bFocusNow) SetCommandable(FALSE); else// this won't occur until .2 seconds after entire script has executed. DelayCommand(0.2f, SetCommandable(FALSE)); // If all the commands aren't finished within the time out period (for example, // got stuck on a rock while moving and can't pathfind around it), then we will // recover by becoming commandable again. DelayCommand(fTimeOut, CheckOrderComplete(iOrderNum)); } // destroy oCreature or despawn oCreature if roster member // auto sets plot flag and destroyable attribute so non-roster creatures will be destroyed. void RemoveMyself() { object oCreature = OBJECT_SELF; if (GetIsRosterMember(oCreature)) { // will always work for a roster member (regardless of plot or destroyable flag) DespawnRosterMember(GetRosterNameFromObject(oCreature)); } else { SetPlotFlag(oCreature,FALSE); SetIsDestroyable(TRUE); DestroyObject(oCreature); } } // Action wrapper void ActionRemoveMyself() { ActionDoCommand(RemoveMyself()); } // Force move to exit WP and destroy self or despawn if roster member void ActionForceExit(string sExitTag = "WP_EXIT", int bRun=FALSE) { location lExitLoc = GetLocation(FindDestinationByTag(sExitTag)); ActionForceMoveToLocation(lExitLoc, bRun); ActionDoCommand(SetCommandable(TRUE)); // SetPlotFlag(OBJECT_SELF,FALSE); ActionRemoveMyself(); //ActionDoCommand(DestroyObject(OBJECT_SELF)); SetCommandable(FALSE); } // sets the 2 properties on object for use by gc_node void SetNode(object oObject, int iNodeIndex, int iOnceOnly = TRUE) { // gc_node will look at these vars. SetLocalInt(oObject, "sn_NodeIndex", iNodeIndex); // node index to check for SetLocalInt(oObject, "sn_OnceOnly", iOnceOnly); // signal whether we should clear node if true } // sets a node which should be checked for in conversation w/ gc_node and starts convo void ActionSpeakNode(int iNodeIndex, string sDialog = "", object oObjectToConverseWith = OBJECT_SELF, int iOnceOnly = TRUE) { SetNode(OBJECT_SELF, iNodeIndex, iOnceOnly); ActionStartConversation(oObjectToConverseWith, sDialog); // SpeakOneLinerConversation(sDialog, OBJECT_SELF); } /* // sets a node which should be check for in conversation w/ gc_node and starts convo void ActionStartConversationNode(object oPC, string sConversation, int iNodeIndex) { SetLocalInt(OBJECT_SELF, "sn_OnceOnly", TRUE); SetLocalInt(OBJECT_SELF, "sn_NodeIndex", iNodeIndex); ActionStartConversation(oPC, sConversation, FALSE, FALSE, TRUE); } */ //////////////////////////////////////////////////////////////////////////////// // Helper function. Do not call these directly from outside file //////////////////////////////////////////////////////////////////////////////// // Check that order is complete (N2_ActionOrderNumber will be something other than what we set it to). // If not, we set object to be commandable in hopes of recovering. void CheckOrderComplete(int iOrderNum) { int iSavedOrderNum = GetLocalInt(OBJECT_SELF, "N2_ActionOrderNumber"); if (iSavedOrderNum == iOrderNum) { // time out expired for this order and we are still doing it, so clear it! SetCommandable(TRUE); } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ginc_ai //:: //:: Include file for the multiple custom AI scripts dangling about. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/30/06 // DBR 2/27/06 - DamageSwitch AI fabulousness // DBR 4/05/06 - Support for adding Spell Queue spells on the fly #include "x2_inc_switches" //#include "ginc_debug" #include "x0_i0_combat" //void main() {} //---------------------------------------CONSTANTS (DEFINES) ---------------------------------------------------- const string VAR_NEXT_HANDLER = "HANDLER_INTERUPTED_"; //General Purpose defines const string VAR_AP_BLOCKCOUNT = "AP_BLOCKCOUNT"; const string SCRIPT_BLOCK_COUNTER = "gai_blockedcount_b"; const string VAR_AP_NUM_DAMAGERS = "AP_NUM_DAMAGERS"; //Attack Most Damaged By defines const string VAR_AP_DAMAGER = "AP_DAMAGER_"; const string VAR_AP_DAMAGER_PTS = "AP_DAMAGER_DEALT_"; const string SCRIPT_DAMAGE_TRACKER = "gai_damagetracker_b"; const int ATTACK_PREFERENCE_STRONGEST = 1; //Attack Preference defines const int ATTACK_PREFERENCE_WEAKEST = 2; const int ATTACK_PREFERENCE_GROUPATTACK = 3; const int ATTACK_PREFERENCE_MOSTDAMAGEDBY = 4; const int ATTACK_PREFERENCE_PROTECTOR = 5; const int ATTACK_PREFERENCE_TANK = 6; const int ATTACK_PREFERENCE_CLASS_PRIORITY = 7; const int ATTACK_PREFERENCE_AI_TYPE = 8; const string VAR_AP_NUM_PREF = "AP_NUM_PREFERANCES"; const string VAR_AP_PREF_PREFIX = "AP_PREFERANCE_"; const string VAR_AP_CHANCE_PREFIX = "AP_CHANCE_"; const string SCRIPT_PREFERENCE_DCR = "gai_preference_dcr"; const string VAR_AP_GROUP_TARGET = "AP_GROUP_ATTACK_TARGET"; //Attack in Group defines const string SCRIPT_STAY_CLOSE = "gai_stayclose_b"; //Protector defines const string VAR_P_PROXIMITY_COMBAT = "P_PROX_COMBAT"; const string VAR_P_PROXIMITY = "P_PROX_RUN"; const string VAR_P_PROXIMITY_RUN = "P_PROX"; const string VAR_P_GUARDTHIS = "P_GUARD_THIS"; const string SCRIPT_FINITEPURSUIT_DCR = "gai_finitepursuit_dcr"; //Finite Pursuit defines const string VAR_FP_MAXDIST = "FP_MAXIMUM_PURSUIT"; const string VAR_CS_COUNTERSPELL = "CS_COUNTERSPELL"; //Countercaster defines const string VAR_CS_DISPEL = "CS_DISPEL"; const string SCRIPT_COUNTERSPELL_DCR = "gai_counterspell_dcr"; const string SCRIPT_RUNNING_ALARM_DCR = "gai_runningalarm_dcr"; //RunningAlarm defines const int AI_CLASS_TYPE_MELEE = 200; //Attack Class Priority defines const int AI_CLASS_TYPE_RANGED = 201; const int AI_CLASS_TYPE_SPELLCASTERS = 202; const string VAR_CP_ENTRY_PREFIX = "CP_ENTRY_"; const string VAR_CP_NUM_ENTRIES = "CP_NUM_ENTRY"; const string SCRIPT_CLASS_PRIORITY_DCR = SCRIPT_PREFERENCE_DCR; const int AI_TYPE_RUNNING_ALARM = 1; //Attack AI type Priority defines const int AI_TYPE_COWARD = 2; const int AI_TYPE_PROTECTOR = 3; const int AI_TYPE_TANK = 4; const int AI_TYPE_COUNTER_CASTER= 5; const int AI_TYPE_SPELL_QUEUE = 6; const int AI_TYPE_GROUP_ATTACK = 7; const string VAR_AIP_ENTRY_PREFIX = "AIP_ENTRY_"; const string VAR_AIP_NUM_ENTRIES = "AIP_NUM_ENTRY"; const string SCRIPT_AI_PRIORITY_DCR = SCRIPT_PREFERENCE_DCR; const string sSPELL_QUEUE_ENTRY = "SPELL_QUEUE_"; //Spell Queue defines const string sSPELL_QUEUE_TARGET_ENTRY = "SPELL_QUEUE_TARGET_"; const string sSPELL_QUEUE_NUM_CAST = "WHICH_SPELL_ON"; const string sSPELL_QUEUE_DCR_SCRIPT = SCRIPT_PREFERENCE_DCR; const string sSPELL_QUEUE_ENTRY_CHEAT = "SPELL_QUEUE_CHEAT"; //cheat the spell, or cast it. const string sSPELL_QUEUE_ENTRY_INSTANTCAST = "SPELL_QUEUE_INSTANTCAST"; // cast the spell without using the combat round. const string sIGNORE_COMBAT_DCR = "gai_ignore_dcr"; //ignore combat AI stuff const string VAR_DAMAGE_SWITCH_ON_STATE = "DAM_SWIT_ON"; //Damage Switch stuff //-------------------------------PROTOTYPES--------------------------------------------------------------- void AIAssignDCR(object oTarget, string sScript); //general purpose protos int GetHealthPercent(object oTarget=OBJECT_SELF); void AIContinueInterruptedScript(int nEvent); void AIInterceptEventHandler(object oTarget, int nEvent, string sScript); int GetIsAIType(object oTarget,int nAIType); void AIRestoreInterruptedScript(object oTarget, int nEvent); //restores interupted script to what is was, or original void AIAttackPreference(object oFiend,int nAttack_Pref, int nChance=100); //attack preference protos void AIMakeTank(object oTank, int nChance = 100); //tank protos void AIMakeProtector(object oGuard, object oGuardee, int nChance=100, float fProx=6.0f, float fProxCombat=10.0f, float fProxRun=11.0f); //protector protos void AIFinitePursuit(object oAggro, float fMaxDist); //finite pursuit protos void AIMakeCounterCaster(object oCaster, int bCounterSpell, int bDispel); //countercaster protos void AIAttackInOrder(object oAttacker, int nClass); //class priority protos void AISpellQueueEnqueue(object oSpellCaster, int nSpell, string sTarget, int bCheat=FALSE, int bInstantCast = FALSE); //spell queue protos int AIGetIsSpellQueued(object oSpellCaster = OBJECT_SELF); void AIResetType(object oSmartee); //reset to normal AI void AIIgnoreCombat(object oApathetic); //do nothing in combat void AIDamageSwitchEndStatement(); //damageswitch magic void AITurnOnDamageSwitch(object oTarget=OBJECT_SELF); void AITurnOffDamageSwitch(object oTarget=OBJECT_SELF); //-------------------------------GENERAL PURPOSE AI FUNCTIONS--------------------------------------------- //returns an integer 0-100 (or theoretically more) of how much health oTarget has currently of their max int GetHealthPercent(object oTarget=OBJECT_SELF) { int nTotal=GetMaxHitPoints(oTarget); int nCurrent=GetCurrentHitPoints(oTarget); if (nCurrent==0) return 0; if (nCurrent==nTotal) return 100; return FloatToInt( IntToFloat(nCurrent) / IntToFloat(nTotal) * 100.0f ); } //Assigns a custom DCR to a creature. Used to set custom behavior/AI during combat. DCR = DetermineCombatRound. void AIAssignDCR(object oTarget, string sScript) { SetCreatureOverrideAIScript(oTarget,sScript); } //Used in a interupt script. When a creature's event handlers are intercepted with AIInterceptEventHandler(), // this must be called in the inserted script for the oriningal script to run. Can be chained/stacked. void AIContinueInterruptedScript(int nEvent) { string sTempStorage="",sCheck; int i=0; while((sCheck=GetLocalString(OBJECT_SELF,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(++i)))!="") sTempStorage=sCheck; if (sTempStorage=="") return; i-=1; DeleteLocalString(OBJECT_SELF,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i)); ExecuteScript(sTempStorage,OBJECT_SELF); SetLocalString(OBJECT_SELF,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i),sTempStorage); } //This hijacks a creature's (oTarget's) Event Handler and inserts a provided script. // nEvent = CREATURE_SCRIPT_ON_ constant (nwscript.nss). // sScript = Script to insert. This script must contain AIContinueInterruptedScript if the previous interupted scripts are to be run. void AIInterceptEventHandler(object oTarget, int nEvent, string sScript) { string sOld = GetEventHandler(oTarget,nEvent); if (sOld=="")//was no script there, so we just put ours there { SetEventHandler(oTarget,nEvent,sScript); return; } int i=1; while(GetLocalString(oTarget,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i))!="") i++; SetLocalString(oTarget,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i),sOld); SetEventHandler(oTarget,nEvent,sScript); } void AIRestoreInterruptedScript(object oTarget,int nEvent) { string sLast; int i=1; while(GetLocalString(oTarget,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i))!="") i++; sLast = GetLocalString(oTarget,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i-1)); DeleteLocalString(oTarget,VAR_NEXT_HANDLER+IntToString(nEvent)+"_"+IntToString(i-1)); SetEventHandler(oTarget,nEvent,sLast); } void AIResetType(object oSmartee) //reset to normal AI { string sDCR=GetLocalString(oSmartee,CREATURE_VAR_CUSTOM_AISCRIPT); AIAssignDCR(oSmartee,""); int nNumPref=GetLocalInt(oSmartee,VAR_AP_NUM_PREF); DeleteLocalInt(oSmartee,VAR_AP_NUM_PREF); int nType,i; for (i=1;i<=nNumPref;i++) { DeleteLocalInt(oSmartee,VAR_AP_PREF_PREFIX + IntToString(i)); DeleteLocalInt(oSmartee,VAR_AP_CHANCE_PREFIX + IntToString(i)); } while (GetEventHandler(oSmartee,CREATURE_SCRIPT_ON_DAMAGED)==SCRIPT_DAMAGE_TRACKER) //restore from MostDamagedBy AIRestoreInterruptedScript(oSmartee,CREATURE_SCRIPT_ON_DAMAGED); while (GetEventHandler(oSmartee,CREATURE_SCRIPT_ON_BLOCKED_BY_DOOR)==SCRIPT_BLOCK_COUNTER) //restore from Pref AIRestoreInterruptedScript(oSmartee,CREATURE_SCRIPT_ON_BLOCKED_BY_DOOR); while (GetEventHandler(oSmartee,CREATURE_SCRIPT_ON_HEARTBEAT)==SCRIPT_STAY_CLOSE) AIRestoreInterruptedScript(oSmartee,CREATURE_SCRIPT_ON_HEARTBEAT); //restore from the protector type DeleteLocalInt(oSmartee,VAR_CP_NUM_ENTRIES); //restore from class priority i=1; while (GetLocalString(oSmartee,sSPELL_QUEUE_TARGET_ENTRY+IntToString(i))!="")//restore from spell queue { DeleteLocalString(oSmartee,sSPELL_QUEUE_TARGET_ENTRY+IntToString(i)); DeleteLocalInt(oSmartee,sSPELL_QUEUE_ENTRY+IntToString(i)); i+=1; } } //Looks for the tell tale signs int GetIsAIType(object oTarget,int nAIType) { if (nAIType==AI_TYPE_RUNNING_ALARM) { if (GetLocalString(oTarget,CREATURE_VAR_CUSTOM_AISCRIPT)==SCRIPT_RUNNING_ALARM_DCR) return TRUE; } else if (nAIType==AI_TYPE_COWARD) { if (GetCombatCondition(X0_COMBAT_FLAG_COWARDLY,oTarget)) return TRUE; } else if (nAIType==AI_TYPE_PROTECTOR) { if (GetEventHandler(oTarget,CREATURE_SCRIPT_ON_HEARTBEAT)==SCRIPT_STAY_CLOSE) return TRUE; } else if (nAIType==AI_TYPE_TANK) { int nNumPreferences=GetLocalInt(oTarget,VAR_AP_NUM_PREF); int i,nPref; for (i=1;i<=nNumPreferences;i++) if (GetLocalInt(oTarget,VAR_AP_PREF_PREFIX + IntToString(i))==ATTACK_PREFERENCE_TANK) return TRUE; } else if (nAIType==AI_TYPE_COUNTER_CASTER) { if (GetLocalString(oTarget,CREATURE_VAR_CUSTOM_AISCRIPT)==SCRIPT_COUNTERSPELL_DCR) return TRUE; } else if (nAIType==AI_TYPE_SPELL_QUEUE) { if (GetLocalString(oTarget,sSPELL_QUEUE_TARGET_ENTRY+IntToString(1))!="") return TRUE; } else if (nAIType==AI_TYPE_GROUP_ATTACK) { int nNumPreferences=GetLocalInt(oTarget,VAR_AP_NUM_PREF); int i,nPref; for (i=1;i<=nNumPreferences;i++) if (GetLocalInt(oTarget,VAR_AP_PREF_PREFIX + IntToString(i))==ATTACK_PREFERENCE_GROUPATTACK) return TRUE; } return FALSE; } //---------------------------------ATTACK PREFERANCE AI SPECIFIC----------------------------------------- //Sets an attack preference on a creature (oFiend). oFiend will use the AI type nAttack_Pref. // nAttack_Pref's (see ATTACK_PREFERENCE_ constant list) can be mixed and matched using nChance. // nChance is the probability out of 100 that nAttack_Pref is chosen. If the chances of all assigned // attack preferences is less than 100, the remainder is used as a chance for a normal DetermineCombatRound(). // Examples: // AttackPref( me , ATTACK_PREFERENCE_STRONGEST, 60 ); // this makes a creature 60% likely to attack the strongest, 40% likely to do a standard combat round. // AttackPref( me , ATTACK_PREFERENCE_MOSTDAMAGEDBY, 80 ); // AttackPref( me , ATTACK_PREFERENCE_GROUPATTACK, 10 ); // AttackPref( me , ATTACK_PREFERENCE_WEAKEST 7 ); // this makes a creature 80% likely to attack who most damaged them, 10% likely to attack with their group, 7% likely to attack the weakest around, and 3% likely for a Standard DCR. // AttackPref( me , ATTACK_PREFERENCE_TANK); // this makes the creaure always use the Tank DCR. no chance for a Standard DCR (Cause nChance defaults to 100) void AIAttackPreference(object oFiend,int nAttack_Pref, int nChance=100) { int nNumPreferences=GetLocalInt(oFiend,VAR_AP_NUM_PREF)+1; SetLocalInt(oFiend,VAR_AP_NUM_PREF,nNumPreferences); SetLocalInt(oFiend,VAR_AP_PREF_PREFIX + IntToString(nNumPreferences), nAttack_Pref); SetLocalInt(oFiend,VAR_AP_CHANCE_PREFIX + IntToString(nNumPreferences), nChance); AIAssignDCR(oFiend,SCRIPT_PREFERENCE_DCR);//set up special DetermineCombatRound for these AI's //special cases require extra work if (nAttack_Pref==ATTACK_PREFERENCE_MOSTDAMAGEDBY)//means we gotta keep track who hurt me the most if (GetEventHandler(oFiend,CREATURE_SCRIPT_ON_DAMAGED)!=SCRIPT_DAMAGE_TRACKER) AIInterceptEventHandler(oFiend,CREATURE_SCRIPT_ON_DAMAGED,SCRIPT_DAMAGE_TRACKER); //if ((nAttack_Pref==ATTACK_PREFERENCE_PROTECTOR)||(nAttack_Pref==ATTACK_PREFERENCE_TANK)) if (nNumPreferences==1) AIInterceptEventHandler(oFiend,CREATURE_SCRIPT_ON_BLOCKED_BY_DOOR,SCRIPT_BLOCK_COUNTER); } //---------------------------------TANK SPECIFIC--------------------------------------------------------- //Makes oTank use the speical AI DCR for Defensice tanks. Plugs into the Attack Preference system and can be mixed with // other AI's using the nChance system. //Tanks will do the following in order: // 1: heal self (potions, spells) if health is below 1/2. // 2: if any friendly spellcaster nearby is being attacked, try to divert the attention by attacking them. // 3: rule 1, but with clerics. and then with rangers. and then with any class. // 4: use improved expertise, expertise, or parry. void AIMakeTank(object oTank, int nChance = 100) { AIAttackPreference(oTank,ATTACK_PREFERENCE_TANK,nChance); } //---------------------------------PRTOECTOR SPECIFIC---------------------------------------------------- //Makes oGuard a protector. Protectors will stay close to oGuardee, and attack anyone who is trying to damage them, or may // be about to damage them. // Plugs in with Attack Preference, and can be used with other Attack Preferences using the nChance system. // fProx = how close oGuard will try to stay to oGuardee. // fProxCombat = how close oGuard will try to stay to oGuardee when they are in combat. // fProxRun = when oGuard gets this distance away from oGuardee, he will run to oGuardee instead of walk. In combat, this // param is not used, and oGuard will always run to oGuardee when fProxCombat distance is exceeeded. void AIMakeProtector(object oGuard, object oGuardee, int nChance=100, float fProx=6.0f, float fProxCombat=10.0f, float fProxRun=11.0f) { SetLocalObject(oGuard,VAR_P_GUARDTHIS,oGuardee); SetLocalFloat(oGuard,VAR_P_PROXIMITY, fProx); SetLocalFloat(oGuard,VAR_P_PROXIMITY_COMBAT, fProxCombat); SetLocalFloat(oGuard,VAR_P_PROXIMITY_RUN, fProxRun); AIAttackPreference(oGuard,ATTACK_PREFERENCE_PROTECTOR,nChance); AIInterceptEventHandler(oGuard,CREATURE_SCRIPT_ON_HEARTBEAT,SCRIPT_STAY_CLOSE);//set up the stayclose hb } //---------------------------------FINITE PURSUIT AI SPECIFIC-------------------------------------------- //Sets a creature to limit how far they wander/stray to attack enemies. "Break off pursuit" void AIFinitePursuit(object oAggro, float fMaxDist) { SetLocalFloat(oAggro,VAR_FP_MAXDIST,fMaxDist); AIAssignDCR(oAggro,SCRIPT_FINITEPURSUIT_DCR); } //---------------------------------COUNTERSPELL AI SPECIFIC---------------------------------------------- //Makes oCaster a counter-caster. Countercasters debuff enemies and have counterspell mode on otherwise. // if bCounterSpell == 1, Counterspell mode is turned on. *NOT WORKING CURRENTLY. SADNESS* // if bDispel == 1, oCaster will cast any Dispel spells on enemies with buffs. void AIMakeCounterCaster(object oCaster, int bCounterSpell, int bDispel) { if (bCounterSpell) SetLocalInt(oCaster,VAR_CS_COUNTERSPELL,1); if (bDispel) SetLocalInt(oCaster,VAR_CS_DISPEL,1); AIAssignDCR(oCaster,SCRIPT_COUNTERSPELL_DCR); } //---------------------------------CLASS PRIORITY AI SPECIFIC--------------------------------------------- //Used to set a list of classes I want to fight in order. Can be called several times in succession to form a list //nClass = CLASS_TYPE_ constant. void AIAttackInOrder(object oAttacker, int nClass) { int nNumEntries = GetLocalInt(oAttacker,VAR_CP_NUM_ENTRIES)+1; SetLocalInt(oAttacker,VAR_CP_NUM_ENTRIES,nNumEntries); SetLocalInt(oAttacker,VAR_CP_ENTRY_PREFIX+IntToString(nNumEntries),nClass); if (nNumEntries==1) AIAssignDCR(oAttacker,SCRIPT_CLASS_PRIORITY_DCR); } //---------------------------------SPELL QUEUE AI SPECIFIC--------------------------------------------- //Used to enqueue spells with the specialty DCR. Meant to be called several times in succession to form a list //nSpell = SPELL_ constant //sTarget = tag of target, or "$PC", "$ENEMY", "$FRIEND", "$SELF" //bCheat = TRUE if caster ignores restrictions and rules and just casts no matter what //bInstant = TRUE if the player casts the spell immediately "for free" without costing a combat round. Just like the ActionCastSpell*() parameter. void AISpellQueueEnqueue(object oSpellCaster, int nSpell, string sTarget, int bCheat = FALSE, int bInstantCast = FALSE) { int nWhichEntry=GetLocalInt(oSpellCaster,sSPELL_QUEUE_NUM_CAST);//Which spell am I on? int index=nWhichEntry+1; while (GetLocalString(oSpellCaster,sSPELL_QUEUE_TARGET_ENTRY+IntToString(index))!="")//find next index index+=1; SetLocalInt(oSpellCaster,sSPELL_QUEUE_ENTRY+IntToString(index),nSpell); SetLocalString(oSpellCaster,sSPELL_QUEUE_TARGET_ENTRY+IntToString(index),sTarget); SetLocalInt(oSpellCaster,sSPELL_QUEUE_ENTRY_CHEAT+IntToString(index),bCheat); SetLocalInt(oSpellCaster,sSPELL_QUEUE_ENTRY_INSTANTCAST+IntToString(index),bInstantCast); if (index==1)//this is the first time I've been enqueued. Make sure I have the AI setup. SetCreatureOverrideAIScript(oSpellCaster,sSPELL_QUEUE_DCR_SCRIPT); } int AIGetIsSpellQueued(object oSpellCaster = OBJECT_SELF) { int nWhichEntry=GetLocalInt(oSpellCaster,sSPELL_QUEUE_NUM_CAST)+1;//Which spell am I on? string sTarget = GetLocalString(oSpellCaster,sSPELL_QUEUE_TARGET_ENTRY+IntToString(nWhichEntry)); if (sTarget=="") //see if we are out of spells queued up return FALSE; return TRUE; } //----------------------------------DO NOTHING! AI TYPE------------------------------------------------------- void AIIgnoreCombat(object oApathetic) { AIAssignDCR(oApathetic,sIGNORE_COMBAT_DCR); } //-----------------------------------DAMAGE SWITCH AI TYPE----------------------------------------------------- void AITurnOnDamageSwitch(object oTarget=OBJECT_SELF) { if (GetLocalInt(oTarget,VAR_DAMAGE_SWITCH_ON_STATE)==1) return; SetLocalInt(oTarget,VAR_DAMAGE_SWITCH_ON_STATE,1); AIInterceptEventHandler(oTarget,CREATURE_SCRIPT_ON_DAMAGED,GetLocalString(oTarget,"SpawnScript")); } void AITurnOffDamageSwitch(object oTarget=OBJECT_SELF) { SetLocalInt(oTarget,VAR_DAMAGE_SWITCH_ON_STATE,-1); } void AIDamageSwitchEndStatement() { int nOn=GetLocalInt(OBJECT_SELF,VAR_DAMAGE_SWITCH_ON_STATE);//make sure DamageSwitch event is captured if (nOn==0) //first inital call, before damage was dealt { AITurnOnDamageSwitch(); return; } if (nOn==-1) //I am being turned off { AIContinueInterruptedScript(CREATURE_SCRIPT_ON_DAMAGED); AIRestoreInterruptedScript(OBJECT_SELF,CREATURE_SCRIPT_ON_DAMAGED); DeleteLocalInt(OBJECT_SELF,VAR_DAMAGE_SWITCH_ON_STATE); return; } //otherwise, just continue through to the damaged script. AIContinueInterruptedScript(CREATURE_SCRIPT_ON_DAMAGED); } //----------------------------------------AI PREFERENCE ATTACK TYPE-------------------------------------------- //Used to set a list of AI types I want to fight in order. Can be called several times in succession to form a list //nAI = AI_TYPE_ constant. void AIAttackTypeInOrder(object oAttacker, int nAI) { int nNumEntries = GetLocalInt(oAttacker,VAR_AIP_NUM_ENTRIES)+1; SetLocalInt(oAttacker,VAR_AIP_NUM_ENTRIES,nNumEntries); SetLocalInt(oAttacker,VAR_AIP_ENTRY_PREFIX+IntToString(nNumEntries),nAI); if (nNumEntries==1) AIAssignDCR(oAttacker,SCRIPT_AI_PRIORITY_DCR); } // ginc_alignment /* This include file has functions for adjusting alignment */ // FAB 2/8 // ChazM 3/8/05 - file name changed // This function adjusts oPC's Good/Evil alignment. nChange is from // -3 (truly evil acts) to +3 (truly saintly acts). int AdjustGood(object oPC, int nChange); // This function adjusts oPC's Law/Chaos alignment. nChange is from // -3 (truly chaotic acts) to +3 (truly lawful acts). int AdjustLaw(object oPC, int nChange); int AdjustGood(object oPC, int nChange) { int nAlignCurrent = GetAlignmentGoodEvil( oPC ); // Current alignment int nAdjustment; // How much alignment moves int nAlignScale; // Scale of the alignment (from +3 to -3) // Set their current scale if ( nAlignCurrent >= 85 ) nAlignScale = 3; else if ( nAlignCurrent >= 60 ) nAlignScale = 2; else if ( nAlignCurrent >= 25 ) nAlignScale = 1; else if ( nAlignCurrent >= -24 ) nAlignScale = 0; else if ( nAlignCurrent >= -59 ) nAlignScale = -1; else if ( nAlignCurrent >= -84 ) nAlignScale = -2; else nAlignScale = -3; switch ( nChange ) { case -3: // FIENDISH ACTS switch ( nAlignScale ) { case -3: nAdjustment = -2; break; case -2: nAdjustment = -4; break; case -1: nAdjustment = -71 - nAlignCurrent; break; case 0: nAdjustment = -42 - nAlignCurrent; break; case 1: nAdjustment = -nAlignCurrent; break; case 2: nAdjustment = 42 - nAlignCurrent; break; case 3: nAdjustment = 42 - nAlignCurrent; break; } break; case -2: // MALEVOLENT ACTS switch ( nAlignScale ) { case -3: nAdjustment = 0; break; case -2: nAdjustment = -2; break; case -1: nAdjustment = -4; break; case 0: nAdjustment = -6; break; case 1: nAdjustment = -8; break; case 2: nAdjustment = 42 - nAlignCurrent; break; case 3: nAdjustment = 72 - nAlignCurrent; break; } break; case -1: // IMPISH ACTS switch ( nAlignScale ) { case -3: nAdjustment = 0; break; case -2: nAdjustment = 0; break; case -1: nAdjustment = -1; break; case 0: nAdjustment = -1; break; case 1: nAdjustment = -2; break; case 2: nAdjustment = -3; break; case 3: nAdjustment = 72 - nAlignCurrent; break; } break; case 1: // KIND ACTS switch ( nAlignScale ) { case -3: nAdjustment = 3; break; case -2: nAdjustment = 3; break; case -1: nAdjustment = 2; break; case 0: nAdjustment = 1; break; case 1: nAdjustment = 1; break; case 2: nAdjustment = 0; break; case 3: nAdjustment = 0; break; } break; case 2: // BENEVOLENT ACTS switch ( nAlignScale ) { case -3: nAdjustment = 4; break; case -2: nAdjustment = 4; break; case -1: nAdjustment = 4; break; case 0: nAdjustment = 3; break; case 1: nAdjustment = 2; break; case 2: nAdjustment = 1; break; case 3: nAdjustment = 0; break; } break; case 3: // SAINTLY ACTS switch ( nAlignScale ) { case -3: nAdjustment = 5; break; case -2: nAdjustment = 5; break; case -1: nAdjustment = 5; break; case 0: nAdjustment = 4; break; case 1: nAdjustment = 3; break; case 2: nAdjustment = 2; break; case 3: nAdjustment = 1; break; } break; } if ( nAdjustment > 0 ) AdjustAlignment( oPC,ALIGNMENT_GOOD,nAdjustment ); else AdjustAlignment( oPC,ALIGNMENT_EVIL,-nAdjustment ); return nAdjustment; } int AdjustLaw(object oPC, int nChange) { int nAlignCurrent = GetAlignmentLawChaos( oPC ); // Current alignment int nAdjustment; // How much alignment moves int nAlignScale; // Scale of the alignment (from +3 to -3) // Set their current scale if ( nAlignCurrent >= 85 ) nAlignScale = 3; else if ( nAlignCurrent >= 60 ) nAlignScale = 2; else if ( nAlignCurrent >= 25 ) nAlignScale = 1; else if ( nAlignCurrent >= -24 ) nAlignScale = 0; else if ( nAlignCurrent >= -59 ) nAlignScale = -1; else if ( nAlignCurrent >= -84 ) nAlignScale = -2; else nAlignScale = -3; switch ( nChange ) { case -3: // ANARCHIC ACTS switch ( nAlignScale ) { case -3: nAdjustment = -1; break; case -2: nAdjustment = -2; break; case -1: nAdjustment = -3; break; case 0: nAdjustment = -4; break; case 1: nAdjustment = -5; break; case 2: nAdjustment = -5; break; case 3: nAdjustment = -5; break; } break; case -2: // FEY ACTS switch ( nAlignScale ) { case -3: nAdjustment = 0; break; case -2: nAdjustment = -1; break; case -1: nAdjustment = -2; break; case 0: nAdjustment = -3; break; case 1: nAdjustment = -4; break; case 2: nAdjustment = -4; break; case 3: nAdjustment = -4; break; } break; case -1: // WILD ACTS switch ( nAlignScale ) { case -3: nAdjustment = 0; break; case -2: nAdjustment = 0; break; case -1: nAdjustment = -1; break; case 0: nAdjustment = -1; break; case 1: nAdjustment = -2; break; case 2: nAdjustment = -2; break; case 3: nAdjustment = -3; break; } break; case 1: // HONEST ACTS switch ( nAlignScale ) { case -3: nAdjustment = 3; break; case -2: nAdjustment = 3; break; case -1: nAdjustment = 2; break; case 0: nAdjustment = 1; break; case 1: nAdjustment = 1; break; case 2: nAdjustment = 0; break; case 3: nAdjustment = 0; break; } break; case 2: // ORDERLY ACTS switch ( nAlignScale ) { case -3: nAdjustment = 4; break; case -2: nAdjustment = 4; break; case -1: nAdjustment = 4; break; case 0: nAdjustment = 3; break; case 1: nAdjustment = 2; break; case 2: nAdjustment = 1; break; case 3: nAdjustment = 0; break; } break; case 3: // PARAGON ACTS switch ( nAlignScale ) { case -3: nAdjustment = 5; break; case -2: nAdjustment = 5; break; case -1: nAdjustment = 5; break; case 0: nAdjustment = 4; break; case 1: nAdjustment = 3; break; case 2: nAdjustment = 2; break; case 3: nAdjustment = 1; break; } break; } if ( nAdjustment > 0 ) AdjustAlignment( oPC,ALIGNMENT_LAWFUL,nAdjustment ); else AdjustAlignment( oPC,ALIGNMENT_CHAOTIC,-nAdjustment ); return nAdjustment; } // ginc_autosave.nss /* NWN2 Single Player Auto Save Include */ // BMA-OEI 8/22/06 //temp #include "ginc_debug" const int AUTOSAVE_COOL_DOWN = 5; // in in-game hours const string AUTOSAVE_LAST_SAVE = "00_nAutoSaveLastSave"; // time hash timestamp // Return time hash given nHours and nDays // Ranges between 24 (0 Hour 1 Day) and 695 (23 Hour 28 Day) int GetTimeHash( int nHours, int nDays ); // Return time hash difference (adjusts for wrap around) int GetTimeHashDifference( int nHash1, int nHash2 ); // Return current time hash int GetCurrentTimeHash(); // Return last auto save time hash int GetAutoSaveTimeHash(); // Return TRUE if Single Player and sufficient time has passed since last save int GetAbleToAutoSave( int bUseCoolDown=TRUE ); // Auto Save if able to auto save void AttemptSinglePlayerAutoSave( int bUseCoolDown=TRUE ); // Return time hash given nHours and nDays // Ranges between 24 (0 Hour 1 Day) and 695 (23 Hour 28 Day) int GetTimeHash( int nHours, int nDays ) { int nTimeHash = nHours + ( nDays * 24 ); return ( nTimeHash ); } // Return time hash difference (adjusts for wrap around) int GetTimeHashDifference( int nHash1, int nHash2 ) { int nDifference = nHash1 - nHash2; if ( nDifference < 0 ) { nDifference = nDifference + 672; // wrap around } //PrettyMessage( "GetTimeHashDifference( " + IntToString( nHash1 ) + ", " + IntToString( nHash2 ) + " ) = " + IntToString( nDifference ) ); return ( nDifference ); } // Return current time hash int GetCurrentTimeHash() { int nCurrentHour = GetTimeHour(); int nCurrentDay = GetCalendarDay(); //PrettyMessage( "GetCurrentTimeHash(): nCurrentHour = " + IntToString( nCurrentHour ) + ", nCurrentDay = " + IntToString( GetCalendarDay() ) ); int nTimeHash = GetTimeHash( nCurrentHour, nCurrentDay ); return ( nTimeHash ); } // Return last auto save time hash int GetAutoSaveTimeHash() { int nTimeHash = GetGlobalInt( AUTOSAVE_LAST_SAVE ); return ( nTimeHash ); } // Return TRUE if Single Player and sufficient time has passed since last save int GetAbleToAutoSave( int bUseCoolDown=TRUE ) { int nSinglePlayer = GetIsSinglePlayer(); if ( nSinglePlayer == TRUE ) { if ( bUseCoolDown == TRUE ) { int nCurrentTime = GetCurrentTimeHash(); int nLastSave = GetAutoSaveTimeHash(); //PrettyMessage( "nCurrentTime = " + IntToString( nCurrentTime ) + ", nLastSave = " + IntToString( nLastSave ) ); if ( GetTimeHashDifference( nCurrentTime, nLastSave ) >= AUTOSAVE_COOL_DOWN ) { //PrettyDebug( "GetAbleToAutoSave() = TRUE" ); return ( TRUE ); } } else { //PrettyDebug( "GetAbleToAutoSave() = TRUE" ); return ( TRUE ); } } //PrettyDebug( "GetAbleToAutoSave() = FALSE" ); return ( FALSE ); } // Auto Save if able to auto save void AttemptSinglePlayerAutoSave( int bUseCoolDown=TRUE ) { if ( GetAbleToAutoSave( bUseCoolDown ) == TRUE ) { int nCurrentTime = GetCurrentTimeHash(); SetGlobalInt( AUTOSAVE_LAST_SAVE, nCurrentTime ); DoSinglePlayerAutoSave(); } } // ginc_baddie_stream /* include for streaming baddies */ // ChazM 10/29/95 #include "ginc_misc" const string WP_PREFIX = "wp_"; const string SPAWNED_SUFFIX = "_spawned"; const string NEEDED_SUFFIX = "_needed"; const string KILLED_SUFFIX = "_killed"; int GetBaddiesVar(string sSuffix, string sTemplate); int IncrementBaddiesVar(string sSuffix, string sTemplate, int nCount=1); void RandomSpawn(string sTemplate, string sWaypoint); int MaxAB(int a, int b); //void main() {} // This will create a steady stream of creatures of the specific type // string sResRef - template of creatrure // int iMaxBaddies - max number of baddies to spawn in // on death needs to be set to use script similar to b_baddy_death template // waypoints should be named "wp_" + resref of creature. void CreateStreamedEncounter(string sResRef, int iMaxBaddies) { // Spawn trial baddies string sSpawnPointTag = WP_PREFIX + sResRef; int nBaddiesSpawned = SpawnCreaturesAtWPs(sResRef, sSpawnPointTag); IncrementBaddiesVar(SPAWNED_SUFFIX, sResRef, nBaddiesSpawned); // Track victory condition int nBaddiesNeeded = MaxAB(nBaddiesSpawned, iMaxBaddies); IncrementBaddiesVar(NEEDED_SUFFIX, sResRef, nBaddiesNeeded); } int GetBaddiesVar(string sSuffix, string sTemplate) { object oModule = GetModule(); string sVariable = sTemplate + sSuffix; int nRet = GetLocalInt(oModule, sVariable); //DebugMessage(sTemplate + " has spawned " + IntToString(nRet), 150, 150); return (nRet); } int IncrementBaddiesVar(string sSuffix, string sTemplate, int nCount=1) { object oModule = GetModule(); string sVariable = sTemplate + sSuffix; int nSpawned = GetLocalInt(oModule, sVariable); nSpawned = nSpawned + nCount; SetLocalInt(oModule, sVariable, nSpawned); return (nSpawned); } void RandomSpawn(string sTemplate, string sWaypoint) { DebugPostString(GetFirstPC(), "RandomSpawn(" + sTemplate + "," + sWaypoint + ")", 100, 100, 5.0f); DebugMessage("random spawn " + sTemplate + " at " + sWaypoint); object oWP = GetRandomObjectInArea(sWaypoint); location lWP = GetLocation(oWP); CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lWP, TRUE); IncrementBaddiesVar(SPAWNED_SUFFIX, sTemplate, 1); } // Return max between a or b int MaxAB(int a, int b) { if (a > b) { return (a); } else { return (b); } } // ginc_behavior /* support file for behavior related functions (complex sets of actions and conditions) */ // ChazM 3/9/05 // DBR 5/30/06 - Added mutator SetIsFocused(). Also encapsulated explicit target check into a function. const int FOCUSED_FULL = 2; // fully focused const int FOCUSED_PARTIAL = 1; // will only become unfocused if attacked const int FOCUSED_STANDARD = 0; // treated as full focus when in conversations const int FOCUSED_NONE = -1; // same as original scripts const string VAR_FOCUSED = "Focused"; // --------------------------------------------- // Prototypes // --------------------------------------------- int GetIsFocused(object oTarget=OBJECT_SELF); void SetIsFocused(int nFocusLevel, object oTarget=OBJECT_SELF); //DBR 5/30/06 void StopBehavior(object oObject); void StartBehavior(object oObject); int IsBusy(); int GetIsValidRetaliationTarget(object oTarget, object oRetaliator=OBJECT_SELF); //DBR 5/30/06 // --------------------------------------------- // Functions // --------------------------------------------- int GetIsFocused(object oTarget=OBJECT_SELF) { int iFocused = GetLocalInt(oTarget, VAR_FOCUSED); if (IsInConversation(oTarget) && iFocused != FOCUSED_NONE) { iFocused = FOCUSED_FULL; } return (iFocused); } // Set a creature to be focused DBR 5/30/06 void SetIsFocused(int nFocusLevel, object oTarget=OBJECT_SELF) { SetLocalInt(oTarget, VAR_FOCUSED, nFocusLevel); } // Flag creature's behavior to be stopped void StopBehavior(object oObject) { SetLocalInt(oObject, "Behavior", 1); } // Flag creature's behavior to be started // (on by defualt) void StartBehavior(object oObject) { SetLocalInt(oObject, "Behavior", 0); } // check if creature is busy doing something else, be it combat, conversation, // or some other action on the action queue int IsBusy() { // Behavior flagged to be stopped? if (GetLocalInt(OBJECT_SELF, "Behavior") == 1) return FALSE; if (GetIsInCombat()){ int iTargetType = GetObjectType(GetAttemptedAttackTarget()); // only busy if target is a creature. if (iTargetType == OBJECT_TYPE_CREATURE) return TRUE; else if (Random(10)+1 >= 8) { //SpeakString ("attacking a non creature"); ClearAllActions(TRUE); return FALSE; } else return TRUE; } int iAction = GetCurrentAction(); /* if (iAction == ACTION_ATTACKOBJECT) { SpeakString ("attacking an object"); int iTargetType = GetObjectType(GetAttackTarget()); // only busy if target is a creature. if (iTargetType == OBJECT_TYPE_CREATURE) return TRUE; else { // SpeakString ("attacking a non creature"); return FALSE; } //return FALSE; } */ if (IsInConversation(OBJECT_SELF)) return TRUE; if (iAction != ACTION_INVALID) return TRUE; return FALSE; } // This check is run before the default scripts (nw_c2's) explicitly tell a creature to attack a target // it is NOT checked in Determine Combat Round. int GetIsValidRetaliationTarget(object oTarget, object oRetaliator=OBJECT_SELF) { if (GetPlotFlag(oRetaliator) && !GetIsEnemy(oTarget, oRetaliator)) //please don't attack any neutral or friends if I am plot return FALSE; //not cool to attack this guy return TRUE; //ok to attack this guy } // ginc_companion /* Helper functions for companions. */ // ChazM 8/24/06 - split from ginc_companions, added SetInfluence() // BMA-OEI 9/12/06 -- Added PLAYER_QUEUED_ACTION, Get/SetHasPlayerQueuedAction(), PlayerControlPossessed/Unpossessed(), HandlePlayerControlChanged() // DBR 9/12/06 - Replaced an ActionAttack with a Move and Attack during a de-possession. Also modified GetHasPlayerQueuedAction to discount ActionAttacks as well. // BMA-OEI 9/13/06 -- Set Preferred Attack Target (Checked in HenchmenCombatRound) // ChazM 9/13/06 - Added execute gr_pc_spawn when unpossessing owned character // BMA-OEI 9/13/06 -- Added Get/Set/StorePlayerQueuedTarget() (x0_inc_henai, ginc_cutscene) // ChazM 9/20/06 - ginc_misc, ginc_henchman removed - not dependent // void main(){} //#include "ginc_henchman" //#include "ginc_misc" #include "nw_i0_generic" // has SetAssociateState() #include "x0_i0_petrify" // has RemoveEffectOfType() // Constants const string INFLUENCE_PREFIX = "00_nInfluence"; const int INFLUENCE_MIN = -100; // Companion Influence cap const int INFLUENCE_MAX = 100; const string PLAYER_QUEUED_ACTION = "N2_PLAYER_QUEUED_ACTION"; const string PLAYER_QUEUED_TARGET = "N2_PLAYER_QUEUED_TARGET"; // Prototypes void SetAssociatesState(int nAssociateType, object oPC, int nCondition, int bValid = TRUE); void SetAllAssociatesState(object oMaster, int nCondition, int bValid = TRUE); void ClearAssociatesActions(int nAssociateType, object oPC, int nClearCombatState = FALSE); void ClearAllAssociatesActions(object oMaster, int nClearCombatState = FALSE); void SetAllAssociatesFollow(object oMaster, int bValid=TRUE); int IsHenchman(object oThisHenchman, object oPC); int IsHenchmanByTag(object oPC, string sHenchmanTag=""); object GetHenchmanByTag(object oPC, string sHenchmanTag=""); int RemoveHenchmanByTag(object oPC, string sHenchmanTag=""); void ApplyHenchmanModifier(object oHenchman = OBJECT_SELF); void RemoveHenchmanModifier(object oHenchman = OBJECT_SELF); void AddHenchmanToCompanion(object oCompanionMaster, object oHenchman = OBJECT_SELF); void RemoveHenchmanFromCompanion(object oCompanionMaster, object oHenchman = OBJECT_SELF); object GetPCLeader(object oPC=OBJECT_SELF); int GetIsInRoster(string sRosterName); int IsInParty(string sRosterName); void PrintRosterList(); void ClearRosterList(); void TestAddRosterMemberByTemplate(string sRosterName, string sTemplate); void TestRemoveRosterMember(string sRosterName); int GetIsObjectInParty(object oMember); void DespawnAllRosterMembers(int bExcludeParty=FALSE); // Remove all selectable roster members from oPC's party // - bIgnoreSelectable: If TRUE, also despawn non-Selectable roster members void RemoveRosterMembersFromParty( object oPC, int bDespawnNPC=TRUE, int bIgnoreSelectable=FALSE ); // Return the number of roster members in oPC's party int GetNumRosterMembersInParty( object oPC ); // Despawn non-party roster members and save module state before transitioning to a new module // - sModuleName: Name of module to load // - sWaypoint: Optional starting point for party void SaveRosterLoadModule( string sModuleName, string sWaypoint="" ); // ForceRest() oPC's party void ForceRestParty( object oPC ); int GetInfluence(object oCompanion); int SetInfluence(object oCompanion, int nInfluence); // User defined event handler for possessing a party member // Forces unpossessed, non-associates to follow the new leader void PlayerControlPossessed( object oCreature ); // User defined event handler for unpossessing a party member // Queue player queued action lock to circumvent DetermineCombatRound() void PlayerControlUnpossessed( object oCreature ); // User defined event handler for EVENT_PLAYER_CONTROL_CHANGED (2052) void HandlePlayerControlChanged( object oCreature ); // Return value of player queued action local var // Used to prevent DetermineCombatRound() clearing actions queued during player possession int GetHasPlayerQueuedAction( object oCreature ); // Set player queued action local var to bQueued void SetHasPlayerQueuedAction( object oCreature, int bQueued ); // Return's oCreature's preferred attack target // Used in HenchmenCombatRound() to prevent smashing player queued attacks object GetPlayerQueuedTarget( object oCreature ); // Sets oCreature's preferred attack target to oTarget void SetPlayerQueuedTarget( object oCreature, object oTarget ); // Stores attempted attack target as preferred attack target // Used for HenchmenCombatRound() to prevent smashing player queued attacks // * GetAttemptedAttackTarget() returns caller's ACTION_ATTACKOBJECT target void StorePlayerQueuedTarget(); //------------------------------------------------- // Function Definitions //------------------------------------------------- // Return faction leader of oPC. If faction leader is not a PC, return OBJECT_INVALID. object GetPCLeader(object oPC=OBJECT_SELF) { object oMaster = GetFactionLeader(oPC); if (GetIsPC(oMaster) == FALSE) { oMaster = OBJECT_INVALID; } return (oMaster); } // Check if sRosterName is a valid RosterID int GetIsInRoster(string sRosterName) { string sRosterID = GetFirstRosterMember(); while (sRosterID != "") { if (sRosterID == sRosterName) { return (TRUE); } sRosterID = GetNextRosterMember(); } return (FALSE); } // Add specified companion to roster using either an instance found or else the Template void AddCompanionToRoster(string sRosterName, string sTagName, string sResRef) { string WP_Prefix = "spawn_"; object oCompanion = GetObjectByTag(sTagName); int bInRoster = GetIsInRoster(sRosterName); // check if companion already in roster. if (bInRoster) { // already in roster // shouldn't need to do anything? } else { // not in roster. if (GetIsObjectValid(oCompanion)) { // instance of companion is in world - add him to roster AddRosterMemberByCharacter(sRosterName, oCompanion); } else { // Add companion Blueprint instead AddRosterMemberByTemplate(sRosterName, sResRef); } } } int IsInParty(string sRosterName) { object oPC = GetFirstPC(); object oFM = GetFirstFactionMember(oPC, FALSE); object oCompanion = GetObjectFromRosterName(sRosterName); while(GetIsObjectValid(oFM)) { if(oFM == oCompanion) { return 1; } oFM = GetNextFactionMember(oPC, FALSE); } return 0; } // returns true or false int IsHenchman(object oThisHenchman, object oPC) { if (!GetIsPC(oPC)) return FALSE; object oHenchman; int i; for (i=1; i<=GetMaxHenchmen(); i++) { oHenchman = GetHenchman(oPC, i); if (GetIsObjectValid(oHenchman)) if (oHenchman == oThisHenchman) return TRUE; } return FALSE; } // returns true or false int IsHenchmanByTag(object oPC, string sHenchmanTag="") { return (GetIsObjectValid(GetHenchmanByTag( oPC, sHenchmanTag))); } // Returns henchman with specified tag if found object GetHenchmanByTag(object oPC, string sHenchmanTag="") { if (sHenchmanTag == "") sHenchmanTag = GetTag(OBJECT_SELF); object oHenchman; int i; for (i=1; i<=GetMaxHenchmen(); i++) { oHenchman = GetHenchman(oPC, i); //PrintString ("Henchman [" + IntToString(i) + "] = " + GetName(oHenchman)); if (GetIsObjectValid(oHenchman)) { //PrintString ("Henchman [" + IntToString(i) + "] = " + GetName(oHenchman)); if (sHenchmanTag == GetTag(oHenchman)) return oHenchman; } } return OBJECT_INVALID; } // Removes henchman with specified tag if found int RemoveHenchmanByTag(object oPC, string sHenchmanTag = "") { object oHenchman = GetHenchmanByTag(oPC, sHenchmanTag); if (GetIsObjectValid(oHenchman)) { RemoveHenchman(oPC, oHenchman); AssignCommand(oHenchman, ClearAllActions(TRUE)); // needed to get rid of autofollow return TRUE; } return FALSE; } // Despawn all companions in oPC's party (faction) void DespawnAllCompanions(object oPC) { object oFM = GetFirstFactionMember(oPC, FALSE); string sRosterName; while (GetIsObjectValid(oFM) == TRUE) { PrintString("DespawnAllCompanions: "+GetName(oFM)); if (GetIsRosterMember(oFM) == TRUE) { sRosterName = GetRosterNameFromObject(oFM); DespawnRosterMember(sRosterName); oFM = GetFirstFactionMember(oPC, FALSE); } else { oFM = GetNextFactionMember(oPC, FALSE); } } } void SetAssociatesState(int nAssociateType, object oPC, int nCondition, int bValid = TRUE) { int i = 1; object oAssoc = GetAssociate(nAssociateType, oPC, i); while (GetIsObjectValid(oAssoc)) { AssignCommand(oAssoc, SetAssociateState(nCondition, bValid)); //PrintString("" + GetName(oAssoc) + " - state set to not follow - " + IntToString(bValid)); i++; oAssoc = GetAssociate(nAssociateType, oPC, i); } return; } void SetAllAssociatesState(object oMaster, int nCondition, int bValid = TRUE) { SetAssociatesState(ASSOCIATE_TYPE_ANIMALCOMPANION, oMaster, nCondition, bValid); SetAssociatesState(ASSOCIATE_TYPE_DOMINATED, oMaster, nCondition, bValid); SetAssociatesState(ASSOCIATE_TYPE_FAMILIAR, oMaster, nCondition, bValid); SetAssociatesState(ASSOCIATE_TYPE_HENCHMAN, oMaster, nCondition, bValid); SetAssociatesState(ASSOCIATE_TYPE_SUMMONED, oMaster, nCondition, bValid); return; } void ClearAssociatesActions(int nAssociateType, object oPC, int nClearCombatState = FALSE) { int i = 1; object oAssoc = GetAssociate(nAssociateType, oPC, i); while (GetIsObjectValid(oAssoc)) { AssignCommand(oAssoc, ClearAllActions(nClearCombatState)); i++; oAssoc = GetAssociate(nAssociateType, oPC, i); } return; } void ClearAllAssociatesActions(object oMaster, int nClearCombatState = FALSE) { ClearAssociatesActions(ASSOCIATE_TYPE_ANIMALCOMPANION, oMaster, nClearCombatState); ClearAssociatesActions(ASSOCIATE_TYPE_DOMINATED, oMaster, nClearCombatState); ClearAssociatesActions(ASSOCIATE_TYPE_FAMILIAR, oMaster, nClearCombatState); ClearAssociatesActions(ASSOCIATE_TYPE_HENCHMAN, oMaster, nClearCombatState); ClearAssociatesActions(ASSOCIATE_TYPE_SUMMONED, oMaster, nClearCombatState); } void SetAllAssociatesFollow(object oMaster, int bValid=TRUE) { // followers use ActionForceFollowObject to follow PC. This can only be stopped with a // Clear all actions. if (bValid == FALSE) ClearAllAssociatesActions(oMaster); SetAllAssociatesState(oMaster, NW_ASC_MODE_STAND_GROUND, !bValid); } // apply an AttackIncrease or Decrease effect to henchman of a companion based on the influence // the PC has with the companion void ApplyHenchmanModifier(object oHenchman = OBJECT_SELF) { object oCompanionMaster = GetMaster(oHenchman); int iInfluence = GetInfluence(oCompanionMaster); int iModifier = iInfluence/10; effect eAttack; if (iModifier > 0) eAttack = EffectAttackIncrease(iModifier); else if (iModifier < 0) eAttack = EffectAttackDecrease(abs(iModifier)); if (iModifier != 0) ApplyEffectToObject(DURATION_TYPE_PERMANENT, eAttack, oHenchman); } // Remove the effect applied with ApplyHenchmanModifier(). Note that all effects of given types are removed // (including those derived from other sources such as spells). void RemoveHenchmanModifier(object oHenchman = OBJECT_SELF) { RemoveEffectOfType(oHenchman, EFFECT_TYPE_ATTACK_DECREASE); RemoveEffectOfType(oHenchman, EFFECT_TYPE_ATTACK_INCREASE); } // Adds a henchman and applies modifiers void AddHenchmanToCompanion(object oCompanionMaster, object oHenchman = OBJECT_SELF) { AddHenchman (oCompanionMaster, oHenchman); ApplyHenchmanModifier(oHenchman); } // Removes a henchman and modifiers void RemoveHenchmanFromCompanion(object oCompanionMaster, object oHenchman = OBJECT_SELF) { RemoveHenchmanModifier(oHenchman); RemoveHenchman(oCompanionMaster, oHenchman); } // List roster member names on screen void PrintRosterList() { int nCount = 0; string sRosterName = GetFirstRosterMember(); PrettyMessage("Printing Roster List..."); while (sRosterName != "") { nCount = nCount + 1; PrettyMessage(" Member " + IntToString(nCount) + ": " + sRosterName); sRosterName = GetNextRosterMember(); } PrettyMessage("Roster List finished (" + IntToString(nCount) + " members)."); } // Remove all members from roster void ClearRosterList() { int nCount = 0; int bSuccess = 0; string sMember = GetFirstRosterMember(); while (sMember != "") { nCount++; bSuccess = RemoveRosterMember(sMember); if (bSuccess == TRUE) { PrettyMessage("ginc_roster: ClearRosterList() successfully removed " + sMember); } else { PrettyError("ginc_roster: ClearRosterList() could not find " + sMember); } // Reset iterator sMember = GetFirstRosterMember(); } } // Attempt AddRosterMemberByTemplate() void TestAddRosterMemberByTemplate(string sRosterName, string sTemplate) { int bResult = AddRosterMemberByTemplate(sRosterName, sTemplate); if (bResult == TRUE) { PrettyMessage("ginc_roster: successfully added " + sRosterName + " (" + sTemplate + ")"); } else { PrettyError( "ginc_roster: failed to add " + sRosterName + " (" + sTemplate + ")"); } } // Attempt RemoveRosterMember() void TestRemoveRosterMember(string sMember) { int bResult = RemoveRosterMember(sMember); if (bResult == TRUE) { PrettyMessage("ginc_roster: successfully removed " + sMember); } else { PrettyError("ginc_error: failed to remove " + sMember); } } // Check if oMember is in first PC's party (faction) int GetIsObjectInParty(object oMember) { return (GetFactionEqual(oMember, GetFirstPC())); } // Despawn all roster members in module. Option bExcludeParty=TRUE to ignore party members. // Useful to update roster state before a module transition. void DespawnAllRosterMembers(int bExcludeParty=FALSE) { object oMember; string sRosterID = GetFirstRosterMember(); // For each roster ID while (sRosterID != "") { oMember = GetObjectFromRosterName(sRosterID); // If they're in the game if (GetIsObjectValid(oMember) == TRUE) { // And in my party if (GetIsObjectInParty(oMember) == TRUE) { if (bExcludeParty == FALSE) { RemoveRosterMemberFromParty(sRosterID, GetFirstPC(), TRUE); } } else { DespawnRosterMember(sRosterID); } } sRosterID = GetNextRosterMember(); } } // Remove all selectable roster members from oPC's party // - bIgnoreSelectable: If TRUE, also despawn non-Selectable roster members void RemoveRosterMembersFromParty( object oPC, int bDespawnNPC=TRUE, int bIgnoreSelectable=FALSE ) { string sRosterName; // For each party member object oMember = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oMember ) == TRUE ) { sRosterName = GetRosterNameFromObject( oMember ); // If party member is a roster member if ( sRosterName != "" ) { // And party member is not required if ( ( bIgnoreSelectable ) || ( GetIsRosterMemberSelectable( sRosterName ) == TRUE ) ) { // If party member is controlled by a PC if ( GetIsPC( oMember ) == TRUE ) { // Force PC into original character SetOwnersControlledCompanion( oMember ); } RemoveRosterMemberFromParty( sRosterName, oPC, bDespawnNPC ); oMember = GetFirstFactionMember( oPC, FALSE ); } else { oMember = GetNextFactionMember( oPC, FALSE ); } } else { oMember = GetNextFactionMember( oPC, FALSE ); } } } // Return the number of roster members in oPC's party int GetNumRosterMembersInParty( object oPC ) { int nCount = 0; object oMember = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oMember ) == TRUE ) { // If party member has a roster name if ( GetRosterNameFromObject( oMember ) != "" ) { nCount = nCount + 1; } oMember = GetNextFactionMember( oPC, FALSE ); } return ( nCount ); } // Despawn non-party roster members and save module state before transitioning to a new module // - sModuleName: Name of module to load // - sWaypoint: Optional starting point for party void SaveRosterLoadModule( string sModuleName, string sWaypoint="" ) { // Save non-party roster member states DespawnAllRosterMembers( TRUE ); LoadNewModule( sModuleName, sWaypoint ); } // ForceRest() oPC's party void ForceRestParty( object oPC ) { object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oFM ) == TRUE ) { ForceRest( oFM ); oFM = GetNextFactionMember( oPC, FALSE ); } } //////////////////////////// // Influence //////////////////////////// int GetInfluence(object oCompanion) { string sVarInfluence = INFLUENCE_PREFIX + GetTag(oCompanion); int iInfluence = GetGlobalInt(sVarInfluence); return (iInfluence); } void SetInfluence(object oCompanion, int nInfluence) { string sVarInfluence = INFLUENCE_PREFIX + GetTag(oCompanion); if ( nInfluence < INFLUENCE_MIN ) nInfluence = INFLUENCE_MIN; else if ( nInfluence > INFLUENCE_MAX ) nInfluence = INFLUENCE_MAX; SetGlobalInt( sVarInfluence, nInfluence); } // User defined event handler for possessing a party member // Forces unpossessed, non-associates to follow the new leader void PlayerControlPossessed( object oCreature ) { //PrettyDebug( "ginc_companion: " + GetName( oCreature ) + " has been possessed (EVENT_PLAYER_CONTROL_CHANGED)." ); object oLeader = GetFactionLeader( oCreature ); if ( oLeader == oCreature ) { //PrettyDebug ( "ginc_companion: " + GetName( oCreature ) + " is the new party leader!" ); object oPM = GetFirstFactionMember( oCreature, FALSE ); while ( GetIsObjectValid( oPM ) == TRUE ) { // If I'm currently following somebody if ( GetCurrentAction( oPM ) == ACTION_FOLLOW ) { // But I'm not possessed, not myself, and not an associate if ( ( GetIsPC( oPM ) == FALSE ) && ( oPM != oLeader ) && ( GetAssociateType( oPM ) == ASSOCIATE_TYPE_NONE ) ) { AssignCommand( oPM, ClearAllActions() ); AssignCommand( oPM, ActionForceFollowObject( oLeader, GetFollowDistance( oPM ) ) ); } } oPM = GetNextFactionMember( oCreature, FALSE ); } } } // User defined event handler for unpossessing a party member // Queue player queued action lock to circumvent DetermineCombatRound() void PlayerControlUnpossessed( object oCreature ) { //PrettyDebug( "ginc_companion: " + GetName( oCreature ) + " has been unpossessed (EVENT_PLAYER_CONTROL_CHANGED)." ); if (GetIsOwnedByPlayer(oCreature)) { ExecuteScript("gr_pc_spawn", oCreature); } if ( GetCommandable( oCreature ) == TRUE ) { // BMA-OEI 9/13/06: Clear or save preferred attack target AssignCommand( oCreature, StorePlayerQueuedTarget() ); SetHasPlayerQueuedAction( oCreature, TRUE ); AssignCommand( oCreature, ActionDoCommand( SetHasPlayerQueuedAction( oCreature, FALSE ) ) ); } } // User defined event handler for EVENT_PLAYER_CONTROL_CHANGED (2052) void HandlePlayerControlChanged( object oCreature ) { if ( GetIsPC( oCreature ) == TRUE ) { PlayerControlPossessed( oCreature ); } else { PlayerControlUnpossessed( oCreature ); } } // Return value of player queued action local var // Used to prevent DetermineCombatRound() clearing actions queued during player possession int GetHasPlayerQueuedAction( object oCreature ) { int bQueued = GetLocalInt( oCreature, PLAYER_QUEUED_ACTION ); int nAction = GetCurrentAction( oCreature ); // Safety: If following, attacking, or no more actions in queue if ( ( nAction == ACTION_FOLLOW ) || ( nAction == ACTION_ATTACKOBJECT ) || ( GetNumActions( oCreature ) == 0 ) ) { bQueued = FALSE; } return ( bQueued ); } // Set player queued action local var to bQueued void SetHasPlayerQueuedAction( object oCreature, int bQueued ) { SetLocalInt( oCreature, PLAYER_QUEUED_ACTION, bQueued ); } // Return's oCreature's preferred attack target // Used in HenchmenCombatRound() to prevent smashing player queued attacks object GetPlayerQueuedTarget( object oCreature ) { object oTarget = GetLocalObject( oCreature, PLAYER_QUEUED_TARGET ); return ( oTarget ); } // Sets oCreature's preferred attack target to oTarget void SetPlayerQueuedTarget( object oCreature, object oTarget ) { SetLocalObject( oCreature, PLAYER_QUEUED_TARGET, oTarget ); } // Stores attempted attack target as preferred attack target // Used for HenchmenCombatRound() to prevent smashing player queued attacks // * GetAttemptedAttackTarget() returns caller's ACTION_ATTACKOBJECT target void StorePlayerQueuedTarget() { object oTarget = GetAttemptedAttackTarget(); SetPlayerQueuedTarget( OBJECT_SELF, oTarget ); } // ginc_crafting /* Crafting related functions */ // ChazM 12/15/05 // ChazM 1/31/06 Moved lots of functions out to their appropriate include files. // ChazM 1/31/06 Updated/fixed prototypes // ChazM 2/1/06 Added Alchemy and Distillation. Renamed and reorganized numerous functions. // ChazM 2/1/06 Added Wondrous Items // ChazM 2/2/06 Added various 2DA support // ChazM 2/2/06 Added ability to use either 2DA or variables depending on if VAR_REC_SET is set. Reorganized functions. // ChazM 3/23/06 Added ExecuteDistillation() // ChazM 3/23/06 Changed Mold suffix to be a mold prefix to match the current data set // ChazM 3/28/06 Updated crafting to require various feats and skills // ChazM 3/29/06 Added CasterLevel to Magical/Wondrous Crafting, addded additional error codes // ChazM 3/30/06 Added SuccessNotify(), updated Error codes - string refs with real values // ChazM 4/8/06 Added bIdentify param to CreateListOfItemsInInventory() // ChazM 4/11/06 Added MakeRepeatedItemList() // ChazM 4/18/06 Modified CreateMagicalRecipe(), GetTargetItem(), and DoMagicCrafting() to support using item category (instead of tag suffix list) // ChazM 5/5/06 Changed GetRecipeElement() to GetRecipeIntElement() and GetRecipeStringElement() // ChazM 5/30/06 Added SetEnchantedItemName() - used in DoMagicCrafting() // ChazM 5/31/06 Modified SetEnchantedItemName() // ChazM 5/31/06 added strrefs to SetEnchantedItemName() // ChazM 7/14/06 Modified DoMagicCrafting() - Renaming Item only applies to Magic weapons and armor // ChazM 7/29/06 Fix error in DoMundaneCrafting() // ChazM 8/1/06 Max item properties set to 3. Masterwork weapons can be renamed on each enchanting, everything else only on the first enchanting // ChazM 8/11/06 Updated str refs in SetEnchantedItemName() // ChazM 8/11/06 updated CreateDistillationRecipe() - correction // ChazM 8/14/06 added GetExpandedTags(), updated GetSortedItemList() - fix for stacks of items // ChazM 8/16/06 added various workbench identification functions // ChazM 8/27/06 added temp crafting VFX // PKM 08.28.06 put in final VFX // ChazM 9/10/06 Modified ExecuteDistillation() - stacks can now be distilled, added fix for playing special effect // ChazM 9/29/06 DoMagicCrafting() - everything can be renamed upon enchanting, unless it has a special var; refixed SetEnchantedItemName() #include "x0_i0_stringlib" #include "ginc_vars" #include "ginc_item" #include "ginc_debug" #include "ginc_param_const" // ************************ // *** Constants // ************************ const string VAR_REC_SET = "RecipiesSet"; // Global Var const string MAGICAL_RECIPE_PREFIX = "MAG"; const string MUNDANE_RECIPE_PREFIX = "MUN"; const string ALCHEMY_RECIPE_PREFIX = "ALC"; const string ALCHEMY_RECIPE_SUFFIX = "ALC"; const string DISTILLATION_RECIPE_PREFIX = "DIS"; const string DISTILLATION_RECIPE_SUFFIX = "DIS"; // Used by: const string VAR_RECIPE_COUNT = "_COUNT_"; // magical/wondrous, mundane, alchemy, distillation, //const string VAR_RECIPE_REAGENTS = "_LIST_"; // magical/wondrous, mundane, alchemy, distillation, //const string VAR_RECIPE_TAGS = "_TAGS_"; // magical only //const string VAR_RECIPE_EFFECTS = "_EFFECT_"; // magical only //const string VAR_RECIPE_OUTPUT = "_OUT_"; // wondrous, mundane, alchemy, distillation //const string VAR_RECIPE_CRAFT_SKILL = "_SKILL_"; // mundane only //const string VAR_RECIPE_SKILL_LEVEL = "_LEVEL_"; // mundane, alchemy, distillation // apparently this has changed to a suffix. //const string MOLD_SUFFIX = "_mld"; // tag of weapon/armor molds must always have this suffix. const string MOLD_PREFIX = "n2_crft_mold"; // tag of weapon/armor molds must always have this suffix. const string VAR_RECIPE_SPELLID_LIST = "RECIPE_SPELLID_LIST"; // list of SpellID indexes const string VAR_RECIPE_RESREF_LIST = "RECIPE_RESREF_LIST"; // list of mold resref inexes const string VAR_ROW_NUMBER = "ROW_NUMBER"; // 2DA Row Number const string VAR_RECIPE_2DA_INDEXES = "RECIPE_2DA_INDEXES"; // List of info for index 2DA const string CRAFTING_2DA = "crafting"; const string COL_CRAFTING_CATEGORY = "CATEGORY"; // magical/wondrous, mundane, alchemy, distillation, const string COL_CRAFTING_REAGENTS = "REAGENTS"; // magical/wondrous, mundane, alchemy, distillation, const string COL_CRAFTING_TAGS = "TAGS"; // magical only const string COL_CRAFTING_EFFECTS = "EFFECTS"; // magical only const string COL_CRAFTING_OUTPUT = "OUTPUT"; // wondrous, mundane, alchemy, distillation const string COL_CRAFTING_CRAFT_SKILL = "SKILL"; // mundane only const string COL_CRAFTING_SKILL_LEVEL = "LEVEL"; // magical/wondrous, mundane, alchemy, distillation const string CRAFTING_INDEX_2DA = "crafting_index"; //const string COL_CRAFTING_CATEGORY = "CATEGORY"; // this col in both 2DA's const string COL_CRAFTING_START_ROW = "START_ROW"; // TODO: these need to be updated to the real string refs // Error codes - string refs const int ERROR_ITEM_NOT_DISTILLABLE = 174285; //"No match found for this item" const int ERROR_MISSING_REQUIRED_MOLD = 174286; //"No mold found" const int ERROR_RECIPE_NOT_FOUND = 174287; //"No match found for this spell/reagent combo" const int ERROR_TARGET_NOT_FOUND_FOR_RECIPE = 174288; //"couldn't find object for effect to be put on." const int ERROR_INSUFFICIENT_CASTER_LEVEL = 174289; //"Not high enough level of spell caster to use this magical recipe" const int ERROR_INSUFFICIENT_CRAFT_ALCHEMY_SKILL = 174290; const int ERROR_INSUFFICIENT_CRAFT_ARMOR_SKILL = 174291; const int ERROR_INSUFFICIENT_CRAFT_WEAPON_SKILL = 174293; const int ERROR_NO_CRAFT_WONDROUS_FEAT = 174294; const int ERROR_NO_CRAFT_MAGICAL_FEAT = 174295; const int OK_CRAFTING_SUCCESS = 174296; const int ERROR_TARGET_HAS_MAX_ENCHANTMENTS = 182996; // SItem can not be further enchanted.  const int ERROR_UNRECOGNIZED_MORTAR_USAGE = 183206 ; // The mortar & pestle must be used on an alchemist's workbench or on an item. const int ERROR_UNRECOGNIZED_HAMMER_USAGE = 183205 ; // "The smith hammer must be used on a blacksmith's workbench." // this variable is stored on the owned character so that script "gui_name_enchanted_item" can retrieve a reference to the item. const string VAR_ENCHANTED_ITEM_OBJECT = "EnchantedItemObject"; // Standard Workbench Tag Prefixes const string TAG_WORKBENCH_PREFIX1 = "PLC_MC_WBENCH"; const string TAG_WORKBENCH_PREFIX2 = "PLC_MC_CBENCH"; // Alchemy Workbench tags const string TAG_ALCHEMY_BENCH1 = "alchemy_bench"; const string TAG_ALCHEMY_BENCH2 = "PLC_MC_CBENCH01"; const string TAG_ALCHEMY_BENCH3 = "alchemy"; const string VAR_ALCHEMY = "WB_alchemy"; // Blacksmith Workbench tags const string TAG_WORKBENCH1 = "workbench"; const string TAG_WORKBENCH2 = "PLC_MC_CBENCH02"; const string TAG_WORKBENCH3 = "blacksmith"; const string VAR_BLACKSMITH = "WB_blacksmith"; // just like vector, but with ints struct IntVector { int x; int y; int z; }; // ************************ // *** Prototypes // ************************ // data functions string GetMagicalRecipeVar(string sRecipeVar, int iSpellID); string GetMundaneRecipeVar(string sRecipeVar, string sMoldResRef); string GetAlchemyRecipeVar(string sRecipeVar); string GetDistillationRecipeVar(string sRecipeVar); string GetRecipeVar(string sRecipeType, string sRecipeVar, string sCategory); string GetCraftingStringData(string sRecipeType, string sCategory, string sColumn, int iCount); int GetCraftingIntData(string sRecipeType, string sCategory, string sColumn, int iCount); // useful functions (may be moved elsewhere) string MakeList(string sReagent1, string sReagent2="", string sReagent3="", string sReagent4="", string sReagent5="", string sReagent6="", string sReagent7="", string sReagent8="", string sReagent9="", string sReagent10=""); string MakeRepeatedItemList(string sListElement, int iCount); string MakeEncodedEffect(int nPropID, int nParam1 = 0, int nParam2 = 0, int nParam3 = 0, int nParam4 = 0); void ApplyEncodedEffectToItem(string sEncodedEffect, object oItem); void CreateListOfItemsInInventory(string sItemTemplateList, object oTarget, int bIdentify=TRUE); void DestroyItemsInInventory(int iIncludeCategories = ITEM_CATEGORY_ALL, object oTarget=OBJECT_SELF); int Search2DA(string s2DA, string sColumn, string sMatchElement, int iStartRow, int iEndRow); string PadString(int iMinSize, string sValue); // functions for creating recipes void CreateMagicalRecipe(int iSpellId, string sEffect, int iItemCategory, string sReagentList, int iCasterLevel=1); //void CreateMagicalRecipe(int iSpellId, string sEffect, string sTagSuffixList, string sReagentList, int iCasterLevel=1); void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef, int iCasterLevel=1); void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef); void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef); void CreateDistillationRecipe(int iSkillLevel, string sReagent, string sOutputResRefList); // **** 2da output related functions struct IntVector GetRowIndexes(string sCategory); string GetRecipeStringElement(string sRecipeType, string sRecipeVar, string sCategory, int iCount); int GetRecipeIntElement(string sRecipeType, string sRecipeVar, string sCategory, int iCount); string FormatHeaderRow(); string FormatRecipeRow(string sRecipePrefix, string sCategory, int iCount); int OutputRecipeSet(string sRecipePrefix, string sIndex); int OutputRecipeType(string sRecipePrefix, string sIndexList); int OutputRecipes(); string FormatIndexHeaderRow(); string FormatIndexRecipeRow(int iRow, string sCategory, string sRowIndex); int OutputRecipeIndex(); // private (helper) functions for using recipes string GetSortedItemList(int iIncludeCategories = ITEM_CATEGORY_ALL, object oTarget=OBJECT_SELF); int GetInventoryRecipeMatch(string sRecipePrefix, string sIndex, int iIncludeCategories = ITEM_CATEGORY_ALL); int GetRecipeMatch(string sSortedItemList, string sRecipePrefix, string sIndex); struct IntVector GetRowIndexes(string sCategory); int GetCrafting2DARecipeMatch(string sSortedItemList, string sRecipePrefix, string sCategory); object GetTargetItem(int iItemCategory, object oTarget=OBJECT_SELF); string FindMundaneIndexTag(string sTagSuffix, object oObject=OBJECT_SELF); // functions for using recipes void DoMagicCrafting(int iSpellID, object oPC); void DoMundaneCrafting(object oPC); void DoAlchemyCrafting(object oPC); void DoDistillation(object oItem, object oPC); void ExecuteDistillation(int iSkillReq, object oItem, object oPC, string sItemTemplateList); void SuccessNotify(object oPC, int iStrRef=OK_CRAFTING_SUCCESS); void ErrorNotify(object oPC, int iErrorStrRef); void SetEnchantedItemName(object oPC, object oItem); // is workbench functions int IsWorkbench(object oTarget); int IsSmithWorkbench(object oTarget); int IsAlchemyWorkbench(object oTarget); // ************************ // *** Functions // ************************ // workbenches should all have 1 of 2 standard prefixes int IsWorkbench(object oTarget) { int iObjType = GetObjectType(oTarget); if (iObjType != OBJECT_TYPE_PLACEABLE) // smith workbench must be a placeable return FALSE; string sTargetTag = GetTag(oTarget); string sTargetTagPrefix = GetStringLeft(sTargetTag, GetStringLength(TAG_WORKBENCH_PREFIX1)); if ((sTargetTagPrefix == TAG_WORKBENCH_PREFIX1) || (sTargetTagPrefix == TAG_WORKBENCH_PREFIX2)) return TRUE; return FALSE; } // Needed by Smith Hammer which works on Smith Workbench int IsSmithWorkbench(object oTarget) { int iObjType = GetObjectType(oTarget); if (iObjType != OBJECT_TYPE_PLACEABLE) // smith workbench must be a placeable return FALSE; // smith workbench can be identified by it's tag or by a local variable string sTargetTag = GetTag(oTarget); if ((sTargetTag == TAG_WORKBENCH1) || (sTargetTag == TAG_WORKBENCH2) || (sTargetTag == TAG_WORKBENCH3)) return TRUE; if (GetLocalInt(oTarget, VAR_BLACKSMITH) == TRUE) return TRUE; return FALSE; } // Needed by Mortar & Pestle which only works on Alchemy Workbench int IsAlchemyWorkbench(object oTarget) { int iObjType = GetObjectType(oTarget); if (iObjType != OBJECT_TYPE_PLACEABLE) // alchemy workbench must be a placeable return FALSE; // alchemy workbench can be identified by it's tag or by a local variable string sTargetTag = GetTag(oTarget); if ((sTargetTag == TAG_ALCHEMY_BENCH1) || (sTargetTag == TAG_ALCHEMY_BENCH2) || (sTargetTag == TAG_ALCHEMY_BENCH3)) return TRUE; if (GetLocalInt(oTarget, VAR_ALCHEMY) == TRUE) return TRUE; return FALSE; } void output(string sText, object oTarget = OBJECT_SELF) { PrettyMessage(sText); //PrintString(sText); //AssignCommand(oTarget, SpeakString(sText)); } // =========================================== // Data Functions // =========================================== // Recipe info is stored in globals with the following format: // MAG_[LIST/TAGS/EFFECT]__X - where X is the index string GetMagicalRecipeVar(string sRecipeVar, int iSpellID) { string sVarName = GetRecipeVar(MAGICAL_RECIPE_PREFIX, sRecipeVar, IntToString(iSpellID)); return (sVarName); } // Recipe info is stored in globals with the following format: // MUN_[LIST/...]__X string GetMundaneRecipeVar(string sRecipeVar, string sMoldResRef) { string sVarName = GetRecipeVar(MUNDANE_RECIPE_PREFIX, sRecipeVar, sMoldResRef); return (sVarName); } // Recipe info is stored in globals with the following format: // ALC_[LIST/...]_ALC_X string GetAlchemyRecipeVar(string sRecipeVar) { string sVarName = GetRecipeVar(ALCHEMY_RECIPE_PREFIX, sRecipeVar, ALCHEMY_RECIPE_SUFFIX); return (sVarName); } string GetDistillationRecipeVar(string sRecipeVar) { string sVarName = GetRecipeVar(DISTILLATION_RECIPE_PREFIX, sRecipeVar, DISTILLATION_RECIPE_SUFFIX); return (sVarName); } // Get Recipe Variable Name (used w/ SetGlobalArray*()) string GetRecipeVar(string sRecipeType, string sRecipeVar, string sCategory) { string sVarName = sRecipeType + sRecipeVar + sCategory + "_"; // tbd: should probably do a check to ensure string length not to long. return (sVarName); } // Get Specific RecipeElement from global var string GetRecipeStringElement(string sRecipeType, string sRecipeVar, string sCategory, int iCount) { string sVarRecipeList = GetRecipeVar(sRecipeType, sRecipeVar, sCategory); return (GetGlobalArrayString(sVarRecipeList, iCount)); } // Get Specific RecipeElement from global var int GetRecipeIntElement(string sRecipeType, string sRecipeVar, string sCategory, int iCount) { string sVarRecipeList = GetRecipeVar(sRecipeType, sRecipeVar, sCategory); return (GetGlobalArrayInt(sVarRecipeList, iCount)); } int UsingVariables() { return (GetGlobalInt(VAR_REC_SET)); } // unified crafting data retrieval from global variables or 2da files. // If globals variables are set then we use global vars. // sRecipeType - var - magical, mundane, etc - used as prefix of var name // sCategory - var - spell id or other info used to determine var name // sColumn - var/2da - the column of data we want (reagents, effects, etc.) // iCount - var/2da - the count for var name -or- the index into the crafting.2da string GetCraftingStringData(string sRecipeType, string sCategory, string sColumn, int iCount) { string sStringData; if (UsingVariables()) { //string sGlobalArrayVar = GetRecipeVar(sRecipeType, sColumn, sCategory); //sStringData = GetGlobalArrayString(sGlobalArrayVar, iCount); sStringData = GetRecipeStringElement(sRecipeType, sColumn, sCategory, iCount); } else // 2da version: sStringData = Get2DAString(CRAFTING_2DA, sColumn, iCount); return(sStringData); } int GetCraftingIntData(string sRecipeType, string sCategory, string sColumn, int iCount) { int iIntData; if (UsingVariables()) iIntData = GetRecipeIntElement(sRecipeType, sColumn, sCategory, iCount); else // 2da version: iIntData = StringToInt(Get2DAString(CRAFTING_2DA, sColumn, iCount)); return(iIntData); // return (StringToInt(GetCraftingStringData(sRecipeType, sCategory, sColumn, iCount))); } // =========================================== // Useful funcs // =========================================== // Set up a list with up to 10 elements // this list is simply a comma delimited string // First element is required. string MakeList(string sReagent1, string sReagent2="", string sReagent3="", string sReagent4="", string sReagent5="", string sReagent6="", string sReagent7="", string sReagent8="", string sReagent9="", string sReagent10="") { string sReagentList; sReagentList = sReagent1; sReagentList += FormListElement(sReagent2); sReagentList += FormListElement(sReagent3); sReagentList += FormListElement(sReagent4); sReagentList += FormListElement(sReagent5); sReagentList += FormListElement(sReagent6); sReagentList += FormListElement(sReagent7); sReagentList += FormListElement(sReagent8); sReagentList += FormListElement(sReagent9); sReagentList += FormListElement(sReagent10); return (sReagentList); } // will create a repeated list of items. string MakeRepeatedItemList(string sListElement, int iCount) { string sList; int i; if (iCount >= 1) sList = sListElement; for (i=2; i<=iCount; i++) sList += FormListElement(sListElement); return (sList); } // Property ID required. See function IPSafeAddItemProperty() in x2_inc_itemprop for supported props and params // Creates a list containing the property and params for the effect to apply. string MakeEncodedEffect(int nPropID, int nParam1 = 0, int nParam2 = 0, int nParam3 = 0, int nParam4 = 0) { string sRecipeEffect; sRecipeEffect = IntToString(nPropID); sRecipeEffect += FormListElement(IntToString(nParam1)); sRecipeEffect += FormListElement(IntToString(nParam2)); sRecipeEffect += FormListElement(IntToString(nParam3)); sRecipeEffect += FormListElement(IntToString(nParam4)); return (sRecipeEffect); } // Apply an encoded effect to an item (created w/ MakeEncodedEffect()) void ApplyEncodedEffectToItem(string sEncodedEffect, object oItem) { output ("applying sEncodedEffect " + sEncodedEffect); int nPropID = GetIntParam(sEncodedEffect, 0); int nParam1 = GetIntParam(sEncodedEffect, 1); int nParam2 = GetIntParam(sEncodedEffect, 2); int nParam3 = GetIntParam(sEncodedEffect, 3); int nParam4 = GetIntParam(sEncodedEffect, 4); itemproperty ip = IPGetItemPropertyByID(nPropID, nParam1, nParam2, nParam3, nParam4); IPSafeAddItemProperty(oItem, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); } // create a comma delimited list of items in the inventory of oTarget // bIdentify: -1 leave as default, FALSE (0) - set as not identified, TRUE (1) - set as identified. void CreateListOfItemsInInventory(string sItemTemplateList, object oTarget, int bIdentify=TRUE) { int nPos = 0; string sItemTemplate = GetStringParam(sItemTemplateList, nPos); object oCreatedObject; while (sItemTemplate != "") { output ("creating :" + sItemTemplate); oCreatedObject = CreateItemOnObject(sItemTemplate, oTarget); // if (bIdentify != -1) SetIdentified(oCreatedObject, bIdentify); nPos++; sItemTemplate = GetStringParam(sItemTemplateList, nPos); } } // Destroy all items that are not base type armor or weapon void DestroyItemsInInventory(int iIncludeCategories = ITEM_CATEGORY_ALL, object oTarget=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oTarget); while (GetIsObjectValid(oItem)) { if (GetIsItemCategory(oItem, iIncludeCategories)) { DestroyObject(oItem, 0.2f); } oItem = GetNextItemInInventory(oTarget); } } // returns row number of match or -1 if not found. // searches from start row to endrow // search stops if empty string is returned (may be due to file, column, or row is not found or entry is "****" int Search2DA(string s2DA, string sColumn, string sMatchElement, int iStartRow, int iEndRow) { int i; string sEntry; for (i = iStartRow; i <= iEndRow; i++) { sEntry = Get2DAString(s2DA, sColumn, i); if (sEntry == sMatchElement) return i; if (sEntry == "") return -1; } return -1; } // 1 2 3 4 5 6 7 8 9 0 // 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 const string BLANK_SPACE_100 = " "; // pad string w/ space to MinSize string PadString(int iMinSize, string sValue) { if (sValue == "" ) sValue = "****"; sValue += " "; int iLength = GetStringLength(sValue); int iNumSpaces = iMinSize - iLength; sValue += GetStringLeft(BLANK_SPACE_100, iNumSpaces); return (sValue); } // =========================================== // functions for creating recipes // =========================================== // Magical recipes always require a spellID which is used as an index to improve search speed // MAG_COUNT__ = array count // MAG_LIST__X = recipe reagents // MAG_TAGS__X = recipe Tag Suffix List // MAG_EFFECT__X = recipe Effect // MAG_LEVEL__X = caster level required void CreateMagicalRecipe(int iSpellId, string sEffect, int iItemCategory, string sReagentList, int iCasterLevel=1) { string sNewList = AppendGlobalList(VAR_RECIPE_SPELLID_LIST, IntToString(iSpellId), TRUE); //output("new spellid list:" + sNewList); string sVarRecipeCount = GetMagicalRecipeVar(VAR_RECIPE_COUNT, iSpellId); int iCount = ModifyGlobalInt(sVarRecipeCount, 1); string sVarRecipeReagents = GetMagicalRecipeVar(COL_CRAFTING_REAGENTS, iSpellId); string sVarRecipeTags = GetMagicalRecipeVar(COL_CRAFTING_TAGS, iSpellId); string sVarRecipeEffect = GetMagicalRecipeVar(COL_CRAFTING_EFFECTS, iSpellId); string sVarRecipeCasterLevel= GetMagicalRecipeVar(COL_CRAFTING_SKILL_LEVEL, iSpellId); sReagentList = Sort(sReagentList); //output("CreateMagicalRecipe: Add " + sReagentList); SetGlobalArrayString(sVarRecipeReagents, iCount, sReagentList); SetGlobalArrayInt(sVarRecipeTags, iCount, iItemCategory); SetGlobalArrayString(sVarRecipeEffect, iCount, sEffect); SetGlobalArrayInt(sVarRecipeCasterLevel, iCount, iCasterLevel); // output ("sVarRecipeEffect = " + sVarRecipeEffect); // output ("sEffect = " + sEffect); } // Wonderous recipes always require a spellID which is used as an index to improve search speed // These recipes are stored together with magical weapon/armor recipes. // MAG_COUNT__ = array count // MAG_LIST__X = recipe reagents // MAG_OUT__X = output // MAG_LEVEL__X = caster level required void CreateWondrousRecipe(int iSpellId, string sReagentList, string sOutputResRef, int iCasterLevel=1) { string sNewList = AppendGlobalList(VAR_RECIPE_SPELLID_LIST, IntToString(iSpellId), TRUE); //output("new spellid list:" + sNewList); string sVarRecipeCount = GetMagicalRecipeVar(VAR_RECIPE_COUNT, iSpellId); int iCount = ModifyGlobalInt(sVarRecipeCount, 1); string sVarRecipeReagents = GetMagicalRecipeVar(COL_CRAFTING_REAGENTS, iSpellId); string sVarRecipeOutput = GetMagicalRecipeVar(COL_CRAFTING_OUTPUT, iSpellId); string sVarRecipeCasterLevel= GetMagicalRecipeVar(COL_CRAFTING_SKILL_LEVEL, iSpellId); sReagentList = Sort(sReagentList); //output("CreateWondrousRecipe: Add " + sReagentList); SetGlobalArrayString(sVarRecipeReagents, iCount, sReagentList); SetGlobalArrayString(sVarRecipeOutput, iCount, sOutputResRef); SetGlobalArrayInt(sVarRecipeCasterLevel, iCount, iCasterLevel); } // Mundane recipes always require a mold which is used as an index to improve search speed // MUN_COUNT__ = array count // MUN_LIST__X = recipe reagents // MUN_OUT__X = output // MUN_SKILL__X = skill to be used (int) // MUN_LEVEL__X = Level of skill required void CreateMundaneRecipe(string sMoldTag, int iCraftSkill, int iSkillLevel, string sReagentList, string sOutputResRef) { string sNewList = AppendGlobalList(VAR_RECIPE_RESREF_LIST, sMoldTag, TRUE); //output("new resref list:" + sNewList); //output("new resref list:" + AppendGlobalList(VAR_RECIPE_RESREF_LIST, sMoldTag, TRUE)); string sVarRecipeCount = GetMundaneRecipeVar(VAR_RECIPE_COUNT, sMoldTag); int iCount = ModifyGlobalInt(sVarRecipeCount, 1); string sVarRecipeReagents = GetMundaneRecipeVar(COL_CRAFTING_REAGENTS, sMoldTag); string sVarRecipeOutput = GetMundaneRecipeVar(COL_CRAFTING_OUTPUT, sMoldTag); string sVarRecipeCraftSkill = GetMundaneRecipeVar(COL_CRAFTING_CRAFT_SKILL, sMoldTag); string sVarRecipeSkillLevel = GetMundaneRecipeVar(COL_CRAFTING_SKILL_LEVEL, sMoldTag); sReagentList += FormListElement(sMoldTag); // add mold Res Ref to the list of reagents sReagentList = Sort(sReagentList); //output("CreateMundaneRecipe: Add recipe [" + IntToString(iCount) + "] - " + sReagentList); SetGlobalArrayString(sVarRecipeReagents, iCount, sReagentList); SetGlobalArrayString(sVarRecipeOutput, iCount, sOutputResRef); SetGlobalArrayInt(sVarRecipeCraftSkill, iCount, iCraftSkill); SetGlobalArrayInt(sVarRecipeSkillLevel, iCount, iSkillLevel); } // Alchemy recipes have no index. Note that this means searches will get slower as more and more // recipes are added, so it should be kept to less than 50 or so. void CreateAlchemyRecipe(int iSkillLevel, string sReagentList, string sOutputResRef) { string sVarRecipeCount = GetAlchemyRecipeVar(VAR_RECIPE_COUNT); int iCount = ModifyGlobalInt(sVarRecipeCount, 1); string sVarRecipeReagents = GetAlchemyRecipeVar(COL_CRAFTING_REAGENTS); string sVarRecipeOutput = GetAlchemyRecipeVar(COL_CRAFTING_OUTPUT); string sVarRecipeSkillLevel = GetAlchemyRecipeVar(COL_CRAFTING_SKILL_LEVEL); sReagentList = Sort(sReagentList); SetGlobalArrayString(sVarRecipeReagents, iCount, sReagentList); SetGlobalArrayString(sVarRecipeOutput, iCount, sOutputResRef); SetGlobalArrayInt(sVarRecipeSkillLevel, iCount, iSkillLevel); } // Distillation recipes have no index. void CreateDistillationRecipe(int iSkillLevel, string sReagent, string sOutputResRefList) { string sVarRecipeCount = GetDistillationRecipeVar(VAR_RECIPE_COUNT); int iCount = ModifyGlobalInt(sVarRecipeCount, 1); string sVarRecipeReagents = GetDistillationRecipeVar(COL_CRAFTING_REAGENTS); string sVarRecipeOutput = GetDistillationRecipeVar(COL_CRAFTING_OUTPUT); string sVarRecipeSkillLevel = GetDistillationRecipeVar(COL_CRAFTING_SKILL_LEVEL); SetGlobalArrayString(sVarRecipeReagents, iCount, sReagent); SetGlobalArrayString(sVarRecipeOutput, iCount, sOutputResRefList); SetGlobalArrayInt(sVarRecipeSkillLevel, iCount, iSkillLevel); } // ==================================================================================== // Output to 2DA // ==================================================================================== // generate a row of info representing a recipe string FormatHeaderRow() { PrintString("2DA V2.0"); PrintString(" "); SetGlobalInt(VAR_ROW_NUMBER, -1); string sOut = ""; sOut += PadString(5, " "); sOut += PadString(15, COL_CRAFTING_CATEGORY); sOut += PadString(100,COL_CRAFTING_REAGENTS); sOut += PadString(20, COL_CRAFTING_TAGS); sOut += PadString(20, COL_CRAFTING_EFFECTS); sOut += PadString(50, COL_CRAFTING_OUTPUT); sOut += PadString(10, COL_CRAFTING_CRAFT_SKILL); sOut += PadString(10, COL_CRAFTING_SKILL_LEVEL); PrintString(sOut); return(sOut); } // generate a row of info representing a recipe string FormatRecipeRow(string sRecipePrefix, string sCategory, int iCount) { //output ("*** *** FormatRecipeRow: sRecipePrefix: " + sRecipePrefix + " sCategory:" + sCategory + " iCount:" + IntToString(iCount)); int iRow = ModifyGlobalInt(VAR_ROW_NUMBER, 1); string sOut = ""; sOut += PadString(5, IntToString(iRow)); sOut += PadString(15, sCategory); sOut += PadString(100, GetRecipeStringElement(sRecipePrefix, COL_CRAFTING_REAGENTS , sCategory, iCount)); sOut += PadString(20, IntToString(GetRecipeIntElement(sRecipePrefix, COL_CRAFTING_TAGS , sCategory, iCount))); sOut += PadString(20, GetRecipeStringElement(sRecipePrefix, COL_CRAFTING_EFFECTS , sCategory, iCount)); sOut += PadString(50, GetRecipeStringElement(sRecipePrefix, COL_CRAFTING_OUTPUT , sCategory, iCount)); sOut += PadString(10, IntToString(GetRecipeIntElement(sRecipePrefix, COL_CRAFTING_CRAFT_SKILL, sCategory, iCount))); sOut += PadString(10, IntToString(GetRecipeIntElement(sRecipePrefix, COL_CRAFTING_SKILL_LEVEL, sCategory, iCount))); PrintString(sOut); return(sOut); } // output all recipes for sRecipePrefix of a specific sIndex int OutputRecipeSet(string sRecipePrefix, string sIndex) { //AppendGlobalList(VAR_RECIPE_2DA_INDEXES, IntToString(GetGlobalInt(VAR_ROW_NUMBER))); AppendGlobalList(VAR_RECIPE_2DA_INDEXES, sIndex); AppendGlobalList(VAR_RECIPE_2DA_INDEXES, IntToString(1+GetGlobalInt(VAR_ROW_NUMBER))); //output ("*** OutputRecipeSet: sRecipePrefix: " + sRecipePrefix + " sIndex:" + sIndex); int iCount = 1; string sVarRecipeList = GetRecipeVar(sRecipePrefix, COL_CRAFTING_REAGENTS, sIndex); string sRecipeList; int bMatch = FALSE; sRecipeList = GetGlobalArrayString(sVarRecipeList, iCount); //output ("sRecipeList[" + IntToString(iCount) + "] = " + sRecipeList); while (sRecipeList != "") { FormatRecipeRow(sRecipePrefix, sIndex, iCount); iCount++; sRecipeList = GetGlobalArrayString(sVarRecipeList, iCount); //output ("sRecipeList[" + IntToString(iCount) + "] = " + sRecipeList); } return (iCount); } // output all recipes of specific type, using the list of indexes to find them all int OutputRecipeType(string sRecipePrefix, string sIndexList) { //output ("OutputRecipeType: sRecipePrefix: " + sRecipePrefix + " sIndexList:" + sIndexList); string sIndex; struct sStringTokenizer stTok = GetStringTokenizer(sIndexList, ","); // loop through recipe index list while (HasMoreTokens(stTok)) { stTok = AdvanceToNextToken(stTok); sIndex = GetNextToken(stTok); OutputRecipeSet(sRecipePrefix, sIndex); } return TRUE; } // Output all recipes int OutputRecipes() { PrintString("Save the following as 'crafting.2da'"); PrintString("==================================================="); FormatHeaderRow(); OutputRecipeType(MAGICAL_RECIPE_PREFIX, GetGlobalString(VAR_RECIPE_SPELLID_LIST)); OutputRecipeType(MUNDANE_RECIPE_PREFIX, GetGlobalString(VAR_RECIPE_RESREF_LIST)); OutputRecipeType(ALCHEMY_RECIPE_PREFIX, ALCHEMY_RECIPE_SUFFIX); OutputRecipeType(DISTILLATION_RECIPE_PREFIX, DISTILLATION_RECIPE_SUFFIX); PrintString("==================================================="); return TRUE; } // generate a row of info representing a recipe string FormatIndexHeaderRow() { PrintString("2DA V2.0"); PrintString(" "); string sOut = ""; sOut += PadString(5, " "); sOut += PadString(15, "CATEGORY"); sOut += PadString(10, "START_ROW"); PrintString(sOut); return(sOut); } // generate a row of info representing a recipe string FormatIndexRecipeRow(int iRow, string sCategory, string sRowIndex) { //output ("*** *** FormatRecipeRow: sRecipePrefix: " + sRecipePrefix + " sCategory:" + sCategory + " iCount:" + IntToString(iCount)); string sOut = ""; sOut += PadString(5, IntToString(iRow)); sOut += PadString(15, sCategory); sOut += PadString(5, sRowIndex); PrintString(sOut); return(sOut); } // Output all recipes int OutputRecipeIndex() { int iRow = 0; PrintString("Save the following as 'crafting_index.2da'"); PrintString("==================================================="); FormatIndexHeaderRow(); string s2DAIndexList = GetGlobalString(VAR_RECIPE_2DA_INDEXES); string sCategory, sRowIndex; struct sStringTokenizer stTok = GetStringTokenizer(s2DAIndexList, ","); // loop through recipe index list while (HasMoreTokens(stTok)) { stTok = AdvanceToNextToken(stTok); sCategory = GetNextToken(stTok); stTok = AdvanceToNextToken(stTok); sRowIndex = GetNextToken(stTok); FormatIndexRecipeRow(iRow, sCategory, sRowIndex); iRow++; } PrintString("==================================================="); return TRUE; } // ==================================================================================== // Helper Functions for Using Recipes // ==================================================================================== // return a list of tags to represent a stack of items // never starts or ends w/ a seperator, so can be use just like a single tag for list making string GetExpandedTags(object oItem) { string sTag = GetTag(oItem); int iStackSize = GetItemStackSize(oItem); if (iStackSize < 1) iStackSize = 1; // just in case... string sRet = MakeRepeatedItemList (sTag, iStackSize); return (sRet); } // get all items in specified categories and sort the tags into an alphabetical list string GetSortedItemList(int iIncludeCategories = ITEM_CATEGORY_ALL, object oTarget=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oTarget); string sItemList = ""; while (GetIsObjectValid(oItem)) { if (GetIsItemCategory(oItem, iIncludeCategories)) { if (sItemList == "") sItemList += GetExpandedTags(oItem); else sItemList += FormListElement(GetExpandedTags(oItem)); } oItem = GetNextItemInInventory(oTarget); } sItemList = Sort(sItemList); return (sItemList); } // Creates a sorted list from an inventory, including only iIncludeCategories // return index of the sorted list for this sRecipePrefix and sIndex, -1 if not found int GetInventoryRecipeMatch(string sRecipePrefix, string sIndex, int iIncludeCategories = ITEM_CATEGORY_ALL) { // list of reagent items in forge string sSortedItemList = GetSortedItemList(iIncludeCategories); int iRecipeMatch; iRecipeMatch = GetRecipeMatch(sSortedItemList, sRecipePrefix, sIndex); return (iRecipeMatch); } // return index of sSortedItemList for this sRecipePrefix and sIndex, -1 if not found int GetRecipeMatch(string sSortedItemList, string sRecipePrefix, string sIndex) { output ("sSortedItemList = " + sSortedItemList); int iCount = 1; // do 2da look up instead if not using variables. if (!UsingVariables()) { iCount = GetCrafting2DARecipeMatch(sSortedItemList, sRecipePrefix, sIndex); return (iCount); } string sVarRecipeList = GetRecipeVar(sRecipePrefix, COL_CRAFTING_REAGENTS, sIndex); string sRecipeList; int bMatch = FALSE; sRecipeList = GetGlobalArrayString(sVarRecipeList, iCount); output ("sRecipeList[" + IntToString(iCount) + "] = " + sRecipeList); while ((sRecipeList != "") && (bMatch == FALSE)) { if (sSortedItemList == sRecipeList) bMatch = TRUE; else { iCount++; sRecipeList = GetGlobalArrayString(sVarRecipeList, iCount); output ("sRecipeList[" + IntToString(iCount) + "] = " + sRecipeList); } } if (bMatch == FALSE) iCount = -1; return (iCount); } // returns the start and end index rows for this category struct IntVector GetRowIndexes(string sCategory) { int iRow = -1; struct IntVector iv; iv.x = -1; iv.y = -1; int iIndexRow = Search2DA(CRAFTING_INDEX_2DA, COL_CRAFTING_CATEGORY, sCategory, 0, 100); if (iIndexRow == -1) { output ("index not found."); } else { iv.x = StringToInt(Get2DAString(CRAFTING_INDEX_2DA, COL_CRAFTING_START_ROW, iIndexRow)); // ending row is 1 less than the value of the next start row iv.y = StringToInt(Get2DAString(CRAFTING_INDEX_2DA, COL_CRAFTING_START_ROW, iIndexRow+1))-1; if (iv.y == -1) iv.y = 10000; // go to the end. } return (iv); } // return index of sSortedItemList for this sRecipePrefix and sIndex, -1 if not found int GetCrafting2DARecipeMatch(string sSortedItemList, string sRecipePrefix, string sCategory) { output ("sSortedItemList = " + sSortedItemList); int iCrafting2DARow = -1; struct IntVector iv = GetRowIndexes(sCategory); if (iv.x != -1) iCrafting2DARow = Search2DA(CRAFTING_2DA, COL_CRAFTING_REAGENTS, sSortedItemList, iv.x, iv.y); return (iCrafting2DARow); } // todo - actually use taglist to verify object // object GetTargetItem(int iItemCategory, object oTarget=OBJECT_SELF) { object oItem = OBJECT_INVALID; //string sVarTagList = GetMagicalRecipeVar(COL_CRAFTING_TAGS, iSpellId); //string sTagList = GetGlobalArrayString(sVarTagList, iCount); oItem = GetFirstItemInInventory(oTarget); //string sItemList = ""; while (GetIsObjectValid(oItem)) { if (GetItemCategory(oItem) == iItemCategory) break; oItem = GetNextItemInInventory(oTarget); } return oItem; } // looks for first object in inventory with sTagSuffix and returns full tag. string FindMundaneIndexTag(string sTagPrefix, object oObject=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oObject); int iItemCount=0; int bFound = FALSE; string sRet = ""; int iPrefixSize = GetStringLength(sTagPrefix); while (GetIsObjectValid(oItem) && !bFound) { if (GetStringLeft(GetTag(oItem), iPrefixSize) == sTagPrefix) { bFound = TRUE; sRet = GetTag(oItem); } else oItem = GetNextItemInInventory(oObject); } return sRet; } // Count the number of item properties int GetNumberItemProperties(object oItem) { int iItemPropCount = 0; //Get the first itemproperty itemproperty ipLoop=GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ipLoop)) { iItemPropCount++; ipLoop=GetNextItemProperty(oItem); } return (iItemPropCount); } // ==================================================================================== // Functions for Using Recipes // ==================================================================================== // Spell cast at workstation // Notes: // This covers two types of crafting: // 1. Magic Crafting requires a set of reagents, an item to work on, and a spell to activate it. // 2. Wondrous Crafting, requires a set of reagents and creates a new item. // // Reagents can not be weapons, armor, or shields. These are ignored when looking at reagent components // if more than 1 weapon and/or armor and/or shield is included with the reagents, the one that will be inspected/affected is not defined void DoMagicCrafting(int iSpellID, object oPC) { string sIndexTag = IntToString(iSpellID); // is there a match for this spell/reagent combo? int iRecipeMatch = GetInventoryRecipeMatch(MAGICAL_RECIPE_PREFIX, sIndexTag, ITEM_CATEGORY_OTHER); //output("iRecipeMatch = " + IntToString(iRecipeMatch)); if (iRecipeMatch == -1) { ErrorNotify(oPC, ERROR_RECIPE_NOT_FOUND); return; } int bWondrousCrafting = TRUE; object oItem; //string sItemTemplate = GetGlobalArrayString(GetMagicalRecipeVar(COL_CRAFTING_OUTPUT, iSpellID), iRecipeMatch); // 2da version: //string sItemTemplate = Get2DAString(CRAFTING_2DA, COL_CRAFTING_OUTPUT, iRecipeMatch); string sItemTemplateList = GetCraftingStringData(MAGICAL_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_OUTPUT, iRecipeMatch); int iReqCasterLevel = GetCraftingIntData(MAGICAL_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_SKILL_LEVEL, iRecipeMatch); int iItemCategory = GetCraftingIntData(MAGICAL_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_TAGS, iRecipeMatch); //output ("DoMagicCrafting() sItemTemplate = " + sItemTemplate); if (sItemTemplateList == "") // only wondrous items have output bWondrousCrafting = FALSE; int iReqFeat; int iError; int iItemPropCount; // check additional criteria if doing Magical Arms Crafting if (bWondrousCrafting) { // wondrous items iReqFeat = FEAT_CRAFT_WONDROUS_ITEMS; iError = ERROR_NO_CRAFT_WONDROUS_FEAT; } else { // magical items iReqFeat = FEAT_CRAFT_MAGIC_ARMS_AND_ARMOR; iError = ERROR_NO_CRAFT_MAGICAL_FEAT; // does the tag match requirements? oItem = GetTargetItem(iItemCategory); //output("oItem = " + GetName(oItem)); if (!GetIsObjectValid(oItem)) { ErrorNotify(oPC, ERROR_TARGET_NOT_FOUND_FOR_RECIPE); return; } // examine target iItemPropCount = GetNumberItemProperties(oItem); if (iItemPropCount >= 3) { ErrorNotify(oPC, ERROR_TARGET_HAS_MAX_ENCHANTMENTS); return; } } // check caster has feat if(!GetHasFeat(iReqFeat,oPC)) { ErrorNotify(oPC, iError); return; } // check we are caster of sufficient level if(GetCasterLevel(oPC) < iReqCasterLevel) { ErrorNotify(oPC, ERROR_INSUFFICIENT_CASTER_LEVEL); return; } // all criteria good to go, do effects DestroyItemsInInventory(ITEM_CATEGORY_OTHER); if (bWondrousCrafting) { CreateListOfItemsInInventory(sItemTemplateList, OBJECT_SELF); // this could be sucked up by RemoveReagents() so must be done after! } else { string sEncodedEffect = GetCraftingStringData(MAGICAL_RECIPE_PREFIX, IntToString(iSpellID), COL_CRAFTING_EFFECTS, iRecipeMatch); ApplyEncodedEffectToItem(sEncodedEffect, oItem); } ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_CRAFT_MAGIC), OBJECT_SELF); // was GetLastSpellCaster() // Charles, the parameter passed to EffectVisualEffect needs to be changed at your leisure SuccessNotify(oPC); // masterwork weapons can be renamed on each enchanting // everything else, only on the first enchanting // Renaming Item only applies to Magic weapons and armor // ChazM 6/29/06 - everything can be renamed upon enchanting, unless it has a special var. if (!bWondrousCrafting) // && //( (iItemPropCount <= 0) || (GetStringLeft(GetTag(oItem), 3) == "mst")) ) { SetEnchantedItemName(oPC, oItem); } } // Smith Hammer used at workstation // Notes: // Mundane crafting requires a set of reagents, a specific skill level, and a smith hammer to activate it. // Reagents can be of any item type. void DoMundaneCrafting(object oPC) { // is there a match for this recipe? string sIndexTag = FindMundaneIndexTag(MOLD_PREFIX); output("Index (Mold) is:" + sIndexTag); if (sIndexTag == "") { ErrorNotify(oPC, ERROR_MISSING_REQUIRED_MOLD); return; } int iRecipeMatch = GetInventoryRecipeMatch(MUNDANE_RECIPE_PREFIX, sIndexTag, ITEM_CATEGORY_ALL); output("iRecipeMatch = " + IntToString(iRecipeMatch)); if (iRecipeMatch == -1) { ErrorNotify(oPC, ERROR_RECIPE_NOT_FOUND); return; } // meet required crafting skill? int iSkill = GetCraftingIntData(MUNDANE_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_CRAFT_SKILL, iRecipeMatch); int iSkillReq = GetCraftingIntData(MUNDANE_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_SKILL_LEVEL, iRecipeMatch); int iPCSkill = GetSkillRank(iSkill, oPC); if (iPCSkill < iSkillReq) { // has insufficient skill int iError = ERROR_INSUFFICIENT_CRAFT_WEAPON_SKILL; if (iSkill == SKILL_CRAFT_ARMOR) { iError = ERROR_INSUFFICIENT_CRAFT_ARMOR_SKILL; } ErrorNotify(oPC, iError); return; } DestroyItemsInInventory(ITEM_CATEGORY_ALL); //CreateOutput(iRecipeMatch, OBJECT_SELF); string sItemTemplateList = GetCraftingStringData(MUNDANE_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_OUTPUT, iRecipeMatch); CreateListOfItemsInInventory(sItemTemplateList, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_CRAFT_BLACKSMITH), OBJECT_SELF); // Charles, the parameter passed to EffectVisualEffect needs to be changed at your leisure SuccessNotify(oPC); } // Mortar and Pestle used at Alchemy workstation // Notes: // Alchemy crafting requires a set of reagents, a specific skill level in Alchemy, and a Mortar & Pestle to activate it. // Reagents can be of any item type. void DoAlchemyCrafting(object oPC) { // is there a match for this recipe? string sIndexTag = ALCHEMY_RECIPE_SUFFIX; // alchemy has no index int iRecipeMatch = GetInventoryRecipeMatch(ALCHEMY_RECIPE_PREFIX, sIndexTag, ITEM_CATEGORY_ALL); output("iRecipeMatch = " + IntToString(iRecipeMatch)); if (iRecipeMatch == -1) { ErrorNotify(oPC, ERROR_RECIPE_NOT_FOUND); return; } // meet required crafting skill? int iSkillReq = GetCraftingIntData(DISTILLATION_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_SKILL_LEVEL, iRecipeMatch); int iPCSkill = GetSkillRank(SKILL_CRAFT_ALCHEMY, oPC); if (iPCSkill < iSkillReq) { // has insufficient skill ErrorNotify(oPC, ERROR_INSUFFICIENT_CRAFT_ALCHEMY_SKILL); return; } DestroyItemsInInventory(ITEM_CATEGORY_ALL); //CreateOutput(iRecipeMatch, OBJECT_SELF); string sItemTemplateList = GetCraftingStringData(ALCHEMY_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_OUTPUT, iRecipeMatch); CreateListOfItemsInInventory(sItemTemplateList, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_CRAFT_ALCHEMY), OBJECT_SELF); // Charles, the parameter passed to EffectVisualEffect needs to be changed at your leisure SuccessNotify(oPC); } // Mortar and Pestle used on an item // Notes: // Distillation requires an acted upon item (reagent), a specific skill level in Alchemy, and a Mortar & Pestle to activate it. // Reagent can be of any item type. void DoDistillation(object oItem, object oPC) { // is there a match for this recipe? string sItemTag = GetTag(oItem); string sIndexTag = DISTILLATION_RECIPE_SUFFIX; // distillation has no index int iRecipeMatch = GetRecipeMatch(sItemTag, DISTILLATION_RECIPE_PREFIX, sIndexTag); output("iRecipeMatch = " + IntToString(iRecipeMatch)); if (iRecipeMatch == -1) { ErrorNotify(oPC, ERROR_ITEM_NOT_DISTILLABLE); // output("No match found for this item"); return; } // lookup skill req int iSkillReq = GetCraftingIntData(DISTILLATION_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_SKILL_LEVEL, iRecipeMatch); string sItemTemplateList = GetCraftingStringData(DISTILLATION_RECIPE_PREFIX, sIndexTag, COL_CRAFTING_OUTPUT, iRecipeMatch); ExecuteDistillation(iSkillReq, oItem, oPC, sItemTemplateList); } void ExecuteDistillation(int iSkillReq, object oItem, object oPC, string sItemTemplateList) { // TODO: meet required crafting skill? int iPCSkill = GetSkillRank(SKILL_CRAFT_ALCHEMY, oPC); if (iPCSkill < iSkillReq) { // has insufficient skill ErrorNotify(oPC, ERROR_INSUFFICIENT_CRAFT_ALCHEMY_SKILL); return; } int iStackSize = GetItemStackSize(oItem); // we can distill multiple objects at once. DestroyObject(oItem); int i; for (i=1; i<= iStackSize; i++) { CreateListOfItemsInInventory(sItemTemplateList, oPC); } //ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_CRAFT_SELF), oPC); // Charles, the parameter passed to EffectVisualEffect needs to be changed at your leisure ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_CRAFT_SELF), GetLocation(oPC)); // Charles, the parameter passed to EffectVisualEffect needs to be changed at your leisure SuccessNotify(oPC); } void SuccessNotify(object oPC, int iStrRef=OK_CRAFTING_SUCCESS) { SendMessageToPCByStrRef(oPC, iStrRef); } void ErrorNotify(object oPC, int iErrorStrRef) { SendMessageToPCByStrRef(oPC, iErrorStrRef); } //PEH-OEI 05/24/06 //This script function displays a text input box popup on the client of the //player passed in as the first parameter. ////// // oPC - The player object of the player to show this message box to // nMessageStrRef- The STRREF for the Message Box message. // sMessage - The text to display in the message box. Overrides anything // - indicated by the nMessageStrRef // sOkCB - The callback script to call if the user clicks OK, defaults // - to none. The script name MUST start with 'gui' // sCancelCB - The callback script to call if the user clicks Cancel, defaults // - to none. The script name MUST start with 'gui' // bShowCancel - If TRUE, Cancel Button will appear on the message box. // sScreenName - The GUI SCREEN NAME to use in place of the default message box. // - The default is SCREEN_STRINGINPUT_MESSAGEBOX // nOkStrRef - The STRREF to display in the OK button, defaults to OK // sOkString - The string to show in the OK button. Overrides anything that // - nOkStrRef indicates if it is not an empty string // nCancelStrRef - The STRREF to dispaly in the Cancel button, defaults to Cancel. // sCancelString - The string to display in the Cancel button. Overrides anything // - that nCancelStrRef indicates if it is anything besides empty string // sDefaultString- The text that gets copied into the input area, // - used as a default answer /* void DisplayInputBox( object oPC, int nMessageStrRef, string sMessage, string sOkCB="", string sCancelCB="", int bShowCancel=FALSE, string sScreenName="", int nOkStrRef=0, string sOkString="", int nCancelStrRef=0, string sCancelString="", string sDefaultString="", string sVariableString="" ); */ // oPC = creator of the enchanted item. // oItem = the enchanted item void SetEnchantedItemName(object oPC, object oItem) { int nMessageStrRef = 181743; string sMessage = ""; // "Please rename the item."; string sOkCB = "gui_name_enchanted_item"; string sCancelCB = ""; int bShowCancel = FALSE; string sScreenName = ""; int nOkStrRef = 181744; string sOkString = ""; int nCancelStrRef = 181745; string sCancelString = ""; string sDefaultString = GetFirstName(oItem); string sVariableString = ""; // the gui script will always run on the owned PC, regardless of who the player has possessed. object oObj = GetOwnedCharacter(oPC); SetLocalObject(oObj, VAR_ENCHANTED_ITEM_OBJECT, oItem); DisplayInputBox( oPC, nMessageStrRef, sMessage, sOkCB, sCancelCB, bShowCancel, sScreenName, nOkStrRef, sOkString, nCancelStrRef, sCancelString, sDefaultString, sVariableString); } //void main() {} // ginc_cutscene // // various cutscene functions // // EPF 4/8/05 // EPF 11/28/05 - added fSafeDelay params for the fading functions // BMA-OEI 1/13/06 - added MakeConversable() // BMA-OEI 1/23/06 - added FireAndForgetConversation() // ChazM 2/7/06 - added struct CutsceneInfo, GetCutsceneData(), ThisCutsceneToPlay() // BMA-OEI 2/7/06 - added GetIsCutscenePending(), ResetCutsceneInfo(), SetupCutsceneInfo() // BMA-OEI 2/27/06 - added PrepareForConversation() // BMA-OEI 3/02/06 - added GetIsPartyInConversation(), SetPartyPlotFlag(), ClearPartyActions(), Hide/ShowHostileCreatures(), JumpPartyToSpeaker() // BMA-OEI 3/6/06 - removed PrepareForConversation(), CombatCutsceneSetup() functions // BMA-OEI 3/7/06 - moved CombatCutsceneCleanUp to local IPoint Cleaner // BMA-OEI 3/7/06 - added Save/LoadStandGroundState() // BMA-OEI 4/3/06 - GetIsEffectTypeBad() - added turned, dominated, cutscene paralyze, cutscene ghost, cutscene immobilize, frightened // BMA-OEI 4/10/06 - HideHostileCreatures() type check creatures and AoEs // BMA-OEI 8/15/06 - Added SetCommandable(TRUE) to MakeConversable() // BMA-OEI 9/13/06 - Clear player queued preffered target in MakeConversable() // BMA-OEI 9/14/06 - Added Save/LoadActionModes(), Save/LoadPartyActionModes() // CombatCutsceneSetup/CleanUp() updated to preserve modes cleared at start of dialog // ChazM 9/15/06 - Added SetCameraFacingPointParty(), SetCameraFacingPoint() (originally by EPF) #include "nw_i0_generic" #include "nw_i0_plot" #include "ginc_companion" //void main(){} //------------------------------------------------------- // *** CONSTANTS AND STRUCTS *** //------------------------------------------------------- // Area Client Enter cutscene struct struct CutsceneInfo { object oSpeaker; // Speaker of conversation to play string sDialog; // Dialog of conversation to play int bCutscenePending; // Cutscene is ready to play int nCutsceneInfoCount; // Track current cutscene being checked }; const string COMBAT_LOCK_VAR = "__bCombatCutsceneLocked"; const string TEMP_HOSTILE_VAR = "__bTempHiddenForCutscene"; const string STAND_GROUND_VAR = "__bStandGroundValue"; const string IPC_RESREF = "plc_ipcleaner"; const string IPC_DELETE_SELF = "__bDeleteSelf"; const int NUM_ACTION_MODES = 11; // 0-11; ACTION_MODE_* const string ACTION_MODE_PREFIX = "__nActionModeStatus"; //------------------------------------------------------- // *** FUNCTION PROTOTYPES *** //------------------------------------------------------- // SetCutsceneModeParty() // // Sets the cutscene mode of oPC's party to be true, thereby freezing all PCs and associates in the party. // if bInCutscene is FALSE, the function returns oPC's party to their normal unfrozen states. // NOTE: internally calls FreezeAllAssociates(). void SetCutsceneModeParty(object oPC, int bInCutscene = TRUE); // FadeToBlackParty() // // Fades out for all PCs in oPC's party. Fades in (from black) if bFadeOut is FALSE. // fFadeSpeed is the time in seconds to complete the fade // fSafeDelay is the time after which the game will automatically fade in, in the event // that the scripter forgot to fade in manually. // nColor is for the color the screen should fade to. void FadeToBlackParty(object oPC, int bFadeOut = TRUE, float fFadeSpeed = 1.f, float fSafeDelay = 15.f, int nColor = 0); // SetCutsceneModeAllPCs() // // Sets the cutscene mode of all PCs in the module to the value of bInCutscene. void SetCutsceneModeAllPCs(int bInCutscene = TRUE); // FadeToBlackAllPCs() // // Fades out for all PCs. Fades in (from black) if bFadeOut is FALSE. // fFadeSpeed is the time in seconds to complete the fade // fSafeDelay is the time after which the game will automatically fade in, in the event // that the scripter forgot to fade in manually. void FadeToBlackAllPCs(int bFadeOut = TRUE, float fFadeSpeed = 1.f, float fSafeDelay = 15.f); // FreezeAllAssociates() // // Calls FreezeAssociate for all NPCs in oPC's party, including familiars, henchmen, etc. // if bValid is FALSE, it will unfreeze the associates. void FreezeAllAssociates(object oPC, int bValid = TRUE); // FreezeAssociate() // // Sets associate state to STAND GROUND, which effectively incapacitates them until their state // is changed again. // oPC is the PC whose associates we're freezing // nNth is the nth instance of that associate type (nth henchman, for instance). // if bValid is FALSE, it will unfreeze the associates. void FreezeAssociate(object oPC, int bValid, int nType, int nNth = 1); // Make oCreature (or faction) conversable (remove bad effects, revive, clear actions) void MakeConversable(object oCreature=OBJECT_SELF, int bFaction=FALSE); // Call appropriate MakeConversable() to prepare for conversation //void PrepareForConversation(object oCreature=OBJECT_SELF); // Prepare and fire conversation immediately void FireAndForgetConversation(object oSpeaker, object oPC, string sDialog); // Determine if a cutscene is waiting to be played int GetIsCutscenePending(struct CutsceneInfo stCI); // Initialize CutsceneInfo struct struct CutsceneInfo ResetCutsceneInfo(struct CutsceneInfo stCI); // Return CutsceneInfo struct of pending cutscene struct CutsceneInfo SetupCutsceneInfo(struct CutsceneInfo stCI, string sSpeakerTag, object oPC, string sDialog, int bCutsceneCondition); // Check if any member of oPC's party is in conversation int GetIsPartyInConversation(object oPC); // Set oPC's party's Plot Flag void SetPartyPlotFlag(object oPC, int bPlotFlag); // Clear all oPC's party's actions void ClearPartyActions(object oPC, int bClearCombatState=FALSE); // ScriptHide all creatures hostile to oPC in area void HideHostileCreatures(object oPC, object oArea=OBJECT_INVALID); // Remove effect cutscene paralyze on oCreature void RemoveEffectCutsceneParalyze(object oCreature); // Show all hostile creatures hidden with HideHostileCreatures() void ShowHostileCreatures(object oPC, object oArea=OBJECT_INVALID); // Jump PC party to oSpeaker void JumpPartyToSpeaker(object oPC, object oSpeaker); // Save PC party's AI states void SavePartyAIState(object oPC); // Load PC party's AI states void LoadPartyAIState(object oPC); // Lock from CombatCutsceneCleanUp until conversation has time to begin void SetCombatCutsceneLocked(int bLocked); // Check if CombatCutsceneSetup has recently been executed int GetIsCombatCutsceneLocked(); // Temp-Lock, save AI states, hide hostile creatures, set party Plot Flag void CombatCutsceneSetup(object oPC); // load AI states, show hostile creatures, set party Plot Flag void CombatCutsceneCleanUp(object oPC, object oArea=OBJECT_INVALID); // Check if we should clean up a CombatCutscene (conversation has ended) void AttemptCombatCutsceneCleanUp(); // Re-queue AttemptCombatCutsceneCleanUp() void QueueCombatCutsceneCleanUp(); // Save ACTION_MODE_* status void SaveActionModes( object oCreature ); // Restore saved ACTION_MODE_* status void LoadActionModes( object oCreature ); // Execute SaveActionModes() for each member in oPC's faction void SavePartyActionModes( object oPC ); // Execute LoadActionModes() for each member in oPC's faction void LoadPartyActionModes( object oPC ); // Set camera of oPC to point in direction of oTarget at the distance and pitch indicated. void SetCameraFacingPoint(object oPC, object oTarget, float fDistance = -1.0, float fPitch = -1.0, int nTransitionType = CAMERA_TRANSITION_TYPE_SNAP); // Set camera facing of all players in oPC's party to point in direction of oTarget at the distance and pitch indicated. void SetCameraFacingPointParty(object oPC, object oTarget, float fDistance = -1.0, float fPitch = -1.0, int nTransitionType = CAMERA_TRANSITION_TYPE_SNAP); //------------------------------------------------------- // *** IMPLEMENTATIONS *** //------------------------------------------------------- void SetCutsceneModeParty(object oPC, int bInCutscene) { object oPCFacMem = GetFirstFactionMember(oPC); //iterate through all PCs in oPC's faction, freeze their associates. while(GetIsObjectValid(oPCFacMem)) { SetCutsceneMode(oPCFacMem, bInCutscene); FreezeAllAssociates(oPCFacMem, bInCutscene); oPCFacMem = GetNextFactionMember(oPC); } } void FadeToBlackParty(object oPC, int bFadeOut, float fFadeSpeed, float fSafeDelay, int nColor) { object oPCFacMem = GetFirstFactionMember(oPC); while(GetIsObjectValid(oPCFacMem)) { if(bFadeOut) { FadeToBlack(oPCFacMem, fFadeSpeed, fSafeDelay, nColor); } else { FadeFromBlack(oPCFacMem, fFadeSpeed); } oPCFacMem = GetNextFactionMember(oPC); } } void SetCutsceneModeAllPCs(int bInCutscene) { object oPC = GetFirstPC(); while(GetIsObjectValid(oPC)) { AssignCommand(oPC, ClearAllActions(TRUE)); SetCutsceneMode(oPC, bInCutscene); oPC = GetNextPC(); } } void FadeToBlackAllPCs(int bFadeOut, float fFadeSpeed, float fSafeDelay) { object oPC = GetFirstPC(); while(GetIsObjectValid(oPC)) { AssignCommand(oPC, ClearAllActions(TRUE)); if(bFadeOut) { FadeToBlack(oPC, fFadeSpeed, fSafeDelay); } else { FadeFromBlack(oPC, fFadeSpeed); } oPC = GetNextPC(); } } void FreezeAssociate(object oPC, int bValid, int nType, int nNth) { object oAssoc = GetAssociate(nType, oPC, nNth); //OnHeartbeat calls ActionForceFollow if the NW_ASC_MODE_STAND_GROUND //flag is set to FALSE. SetAssociateState(NW_ASC_MODE_STAND_GROUND, bValid, oAssoc); //If we're freezing... if(bValid) { //clear any currently active ActionForceFollow commands that //OnHeartbeat might've already triggered. AssignCommand(oAssoc, ClearAllActions(TRUE)); } } void FreezeAllAssociates(object oPC, int bValid) { //Iterate through all possible associates, freezing them one-by-one. UnpossessFamiliar(oPC); object oAssoc; FreezeAssociate(oPC, bValid, ASSOCIATE_TYPE_ANIMALCOMPANION); FreezeAssociate(oPC, bValid, ASSOCIATE_TYPE_DOMINATED); FreezeAssociate(oPC, bValid, ASSOCIATE_TYPE_FAMILIAR); FreezeAssociate(oPC, bValid, ASSOCIATE_TYPE_SUMMONED); int i; for(i = 1; i <= GetMaxHenchmen(); i++) { FreezeAssociate(oPC, bValid, ASSOCIATE_TYPE_HENCHMAN, i); } } // Check if a status effect type can break a conversation // Based on effect types defined in nwscript.nss as of 1/18/06 int GetIsEffectTypeBad(int nEffectType) { return ((nEffectType == EFFECT_TYPE_ENTANGLE) || (nEffectType == EFFECT_TYPE_DEAF) || (nEffectType == EFFECT_TYPE_ARCANE_SPELL_FAILURE) || (nEffectType == EFFECT_TYPE_CHARMED) || (nEffectType == EFFECT_TYPE_CONFUSED) || (nEffectType == EFFECT_TYPE_FRIGHTENED) || (nEffectType == EFFECT_TYPE_PARALYZE) || (nEffectType == EFFECT_TYPE_DAZED) || (nEffectType == EFFECT_TYPE_STUNNED) || (nEffectType == EFFECT_TYPE_SLEEP) || (nEffectType == EFFECT_TYPE_POISON) || (nEffectType == EFFECT_TYPE_DISEASE) || (nEffectType == EFFECT_TYPE_CURSE) || (nEffectType == EFFECT_TYPE_SILENCE) || (nEffectType == EFFECT_TYPE_SLOW) || (nEffectType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE) || (nEffectType == EFFECT_TYPE_INVISIBILITY) || (nEffectType == EFFECT_TYPE_GREATERINVISIBILITY) || (nEffectType == EFFECT_TYPE_DARKNESS) || (nEffectType == EFFECT_TYPE_BLINDNESS) || (nEffectType == EFFECT_TYPE_PETRIFY) || (nEffectType == EFFECT_TYPE_TURNED) || (nEffectType == EFFECT_TYPE_DOMINATED) || (nEffectType == EFFECT_TYPE_CUTSCENE_PARALYZE) || (nEffectType == EFFECT_TYPE_CUTSCENEGHOST) || (nEffectType == EFFECT_TYPE_CUTSCENEIMMOBILIZE) || (nEffectType == EFFECT_TYPE_FRIGHTENED) || (nEffectType == EFFECT_TYPE_POLYMORPH) || (nEffectType == EFFECT_TYPE_SWARM) || (nEffectType == EFFECT_TYPE_WOUNDING) ); //(nEffectType == EFFECT_TYPE_NEGATIVELEVEL) || //(nEffectType == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE) || //(nEffectType == EFFECT_TYPE_ETHEREAL) || } // Clear effects on oCreature void RemoveAllEffects(object oCreature, int bBadOnly) { // Check if oCreature is valid if (GetIsObjectValid(oCreature) == FALSE) return; effect eEffect = GetFirstEffect(oCreature); int nEffectType; // For each effect while (GetIsEffectValid(eEffect) == TRUE) { if (bBadOnly == FALSE) { // Remove them all RemoveEffect(oCreature, eEffect); } else { nEffectType = GetEffectType(eEffect); // Remove if bad if (GetIsEffectTypeBad(nEffectType) == TRUE) { RemoveEffect(oCreature, eEffect); } } eEffect = GetNextEffect(oCreature); } } // Make oCreature (or faction) conversable (remove bad effects, revive) void MakeConversable(object oCreature=OBJECT_SELF, int bFaction=FALSE) { if (bFaction == TRUE) { // Make faction conversable object oMember = GetFirstFactionMember(oCreature, FALSE); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, MakeConversable(oMember, FALSE)); oMember = GetNextFactionMember(oCreature, FALSE); } } else { // BMA-OEI 8/15/06: Unlock action queue SetCommandable( TRUE, oCreature ); // BMA-OEI 9/13/06: Clear player queued preferred target SetPlayerQueuedTarget( oCreature, OBJECT_INVALID ); RemoveAllEffects(oCreature, TRUE); if (GetIsDead(oCreature) == TRUE) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oCreature); } } } // Call appropriate MakeConversable() to prepare for conversation //void PrepareForConversation(object oCreature=OBJECT_SELF) //{ // // Include faction if oCreature is PC // MakeConversable(oCreature, GetIsPC(oCreature)); //} // Prepare and fire conversation immediately void FireAndForgetConversation(object oSpeaker, object oPC, string sDialog) { MakeConversable(oPC, TRUE); MakeConversable(oSpeaker, FALSE); AssignCommand(oSpeaker, ClearAllActions(TRUE)); AssignCommand(oSpeaker, ActionStartConversation(oPC, sDialog, FALSE, FALSE, TRUE, FALSE)); } // Determine if a cutscene is waiting to be played int GetIsCutscenePending(struct CutsceneInfo stCI) { return (stCI.bCutscenePending); } // Initialize CutsceneInfo struct struct CutsceneInfo ResetCutsceneInfo(struct CutsceneInfo stCI) { stCI.bCutscenePending = FALSE; stCI.nCutsceneInfoCount = 0; return (stCI); } // Return CutsceneInfo struct of pending cutscene struct CutsceneInfo SetupCutsceneInfo(struct CutsceneInfo stCI, string sSpeakerTag, object oPC, string sDialog, int bCutsceneCondition) { // Unique cutscene identifier stCI.nCutsceneInfoCount = stCI.nCutsceneInfoCount + 1; if (bCutsceneCondition == TRUE) { string sPlayedVar = "CI_CS_" + IntToString(stCI.nCutsceneInfoCount) + "_PLAYED"; int bPlayedAlready = GetLocalInt(OBJECT_SELF, sPlayedVar); if (bPlayedAlready == FALSE) { if (sSpeakerTag != "") { stCI.oSpeaker = GetNearestObjectByTag(sSpeakerTag, oPC); } if (GetIsObjectValid(stCI.oSpeaker) == FALSE) { PrettyError("SetupCutsceneInfo: ERROR - Pending cutscene with invalid SPEAKER: " + sSpeakerTag + "!"); return (stCI); } if (GetIsPC(stCI.oSpeaker) == TRUE) PrettyError("SetupCutsceneInfo: WARNING - SPEAKER: " + sSpeakerTag + " is controlled by a PC."); stCI.sDialog = sDialog; if (sDialog == "") PrettyError("SetupCutsceneInfo: WARNING - Pending cutscene with unspecified dialog."); stCI.bCutscenePending = TRUE; SetLocalInt(OBJECT_SELF, sPlayedVar, TRUE); } } return (stCI); } // Check if any member of oPC's party is in conversation int GetIsPartyInConversation(object oPC) { object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { if (IsInConversation(oMember) == TRUE) { return (TRUE); } oMember = GetNextFactionMember(oPC, FALSE); } return (FALSE); } // Set oPC's party's Plot Flag void SetPartyPlotFlag(object oPC, int bPlotFlag) { object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { SetPlotFlag(oMember, bPlotFlag); oMember = GetNextFactionMember(oPC, FALSE); } } // Clear all oPC's party's actions void ClearPartyActions(object oPC, int bClearCombatState=FALSE) { object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, ClearAllActions(bClearCombatState)); oMember = GetNextFactionMember(oPC, FALSE); } } // ScriptHide all creatures hostile to oPC in area void HideHostileCreatures( object oPC, object oArea=OBJECT_INVALID ) { // Guarantee a valid oArea if ( GetIsObjectValid( oArea ) == FALSE ) { oArea = GetArea( oPC ); } // Search oArea for valid creatures and area_of_effects //int nCount = 1; //object oCreature = GetNearestCreature( CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE, OBJECT_SELF, nCount, CREATURE_TYPE_SCRIPTHIDDEN, CREATURE_SCRIPTHIDDEN_TRUE ); int nType; object oCreature = GetFirstObjectInArea( oArea ); while (GetIsObjectValid(oCreature) == TRUE) { nType = GetObjectType( oCreature ); // If our object is a creature if ( nType == OBJECT_TYPE_CREATURE ) { // Check if it's visible if ( GetScriptHidden( oCreature ) == FALSE ) { // Check if it's alive if ( GetIsDead( oCreature ) == FALSE ) { // And check if it's hostile to oPC if ( GetIsEnemy( oCreature, oPC ) == TRUE ) { SetScriptHidden( oCreature, TRUE ); SetLocalInt( oCreature, TEMP_HOSTILE_VAR, 1 ); } } } } else if ( nType == OBJECT_TYPE_AREA_OF_EFFECT ) { // Destroy potential problem causing AoEs // The conditional has been commented out because GetIsEnemy may be returning unwanted results // For all intents and purposes, AoEs can be considered harmful in this case and we need to destroy them. //if ( GetIsEnemy( oCreature, oPC) == TRUE ) //{ DestroyObject( oCreature, 0.1f ); //} } //nCount = nCount + 1; //oCreature = GetNearestCreature( CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE, OBJECT_SELF, nCount, CREATURE_TYPE_SCRIPTHIDDEN, CREATURE_SCRIPTHIDDEN_TRUE ); oCreature = GetNextObjectInArea( oArea ); } } // Remove effect cutscene paralyze on oCreature void RemoveEffectCutsceneParalyze(object oCreature) { effect eEffect = GetFirstEffect(oCreature); while (GetIsEffectValid(eEffect) == TRUE) { if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE) { RemoveEffect(oCreature, eEffect); return; } eEffect = GetNextEffect(oCreature); } } // Show all hostile creatures hidden with HideHostileCreatures() void ShowHostileCreatures(object oPC, object oArea=OBJECT_INVALID) { if (GetIsObjectValid(oArea) == FALSE) { oArea = GetArea(oPC); } object oCreature = GetFirstObjectInArea(oArea); while (GetIsObjectValid(oCreature) == TRUE) { if ((GetScriptHidden(oCreature) == TRUE) && (GetLocalInt(oCreature, TEMP_HOSTILE_VAR) == 1)) { SetScriptHidden(oCreature, FALSE); SetLocalInt(oCreature, TEMP_HOSTILE_VAR, 0); } oCreature = GetNextObjectInArea(oArea); } } // Jump PC party to oSpeaker void JumpPartyToSpeaker(object oPC, object oSpeaker) { object oArea = GetArea(oSpeaker); object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { if (GetArea(oMember) == oArea) { AssignCommand(oMember, JumpToObject(oSpeaker)); } oMember = GetNextFactionMember(oPC, FALSE); } } // Save oCreature's Stand Ground state void SaveStandGroundState(object oCreature) { int nValue = GetAssociateState(NW_ASC_MODE_STAND_GROUND, oCreature); SetLocalInt(oCreature, STAND_GROUND_VAR, nValue); } // Load oCreature's Stand Ground state void LoadStandGroundState(object oCreature) { int nValue = GetLocalInt(oCreature, STAND_GROUND_VAR); SetAssociateState(NW_ASC_MODE_STAND_GROUND, nValue, oCreature); } // Lock from CombatCutsceneCleanUp until conversation has time to begin void SetCombatCutsceneLocked(int bLocked) { SetGlobalInt(COMBAT_LOCK_VAR, bLocked); } // Check if CombatCutsceneSetup has recently been executed int GetIsCombatCutsceneLocked() { return GetGlobalInt(COMBAT_LOCK_VAR); } // Temp-Lock, hide hostile creatures, set party Plot Flag void CombatCutsceneSetup(object oPC) { SetCombatCutsceneLocked(1); HideHostileCreatures(oPC); SetPartyPlotFlag(oPC, TRUE); // BMA-OEI 9/14/06: Effort to preserve action mode settings prior to combat cutscenes SavePartyActionModes( oPC ); DelayCommand(1.0f, SetCombatCutsceneLocked(0)); // Clean up when conversation ends object oIPCleaner = CreateObject(OBJECT_TYPE_PLACEABLE, IPC_RESREF, GetLocation(oPC)); AssignCommand(oIPCleaner, QueueCombatCutsceneCleanUp()); } // Show hostile creatures, set party Plot Flag (MUST BE EXECUTED ON AN IPOINT CLEANER) void CombatCutsceneCleanUp(object oPC, object oArea=OBJECT_INVALID) { // BMA-OEI 9/14/06: Effort to preserve action mode settings prior to combat cutscenes LoadPartyActionModes( oPC ); SetPartyPlotFlag(oPC, FALSE); ShowHostileCreatures(oPC, oArea); } // Check if we should clean up a CombatCutscene (conversation has ended) (MUST BE EXECUTED ON AN IPOINT CLEANER) void AttemptCombatCutsceneCleanUp() { if (GetLocalInt(OBJECT_SELF, IPC_DELETE_SELF) == 0) { object oPC = GetFirstPC(); if ((GetIsCombatCutsceneLocked() == 0) && (GetIsPartyInConversation(oPC) == FALSE)) { CombatCutsceneCleanUp(oPC, GetArea(OBJECT_SELF)); SetLocalInt(OBJECT_SELF, IPC_DELETE_SELF, 1); } } else { DestroyObject(OBJECT_SELF); } } // Re-queue AttemptCombatCutsceneCleanUp() (MUST BE EXECUTED ON AN IPOINT CLEANER) void QueueCombatCutsceneCleanUp() { DelayCommand(1.5f, AttemptCombatCutsceneCleanUp()); } // Save ACTION_MODE_* status void SaveActionModes( object oCreature ) { int nMode; int nStatus; for ( nMode = 0; nMode <= NUM_ACTION_MODES; nMode++ ) { nStatus = GetActionMode( oCreature, nMode ); SetLocalInt( oCreature, ACTION_MODE_PREFIX + IntToString( nMode ), nStatus ); } } // Restore saved ACTION_MODE_* status void LoadActionModes( object oCreature ) { int nMode; int nStatus; for ( nMode = 0; nMode <= NUM_ACTION_MODES; nMode++ ) { nStatus = GetLocalInt( oCreature, ACTION_MODE_PREFIX + IntToString( nMode ) ); SetActionMode( oCreature, nMode, nStatus ); } } // Execute SaveActionModes() for each member in oPC's faction void SavePartyActionModes( object oPC ) { object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oFM ) == TRUE ) { SaveActionModes( oFM ); oFM = GetNextFactionMember( oPC, FALSE ); } } // Execute LoadActionModes() for each member in oPC's faction void LoadPartyActionModes( object oPC ) { object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oFM ) == TRUE ) { LoadActionModes( oFM ); oFM = GetNextFactionMember( oPC, FALSE ); } } // Set camera of oPC to point in direction of oTarget at the distance and pitch indicated. void SetCameraFacingPoint(object oPC, object oTarget, float fDistance = -1.0, float fPitch = -1.0, int nTransitionType = CAMERA_TRANSITION_TYPE_SNAP) { vector vPC = GetPosition(oPC); vector vTarget = GetPosition(oTarget); vector vDifference = vTarget - vPC; // this gives us a vector pointing from PC to Target float fDirection = VectorToAngle(vDifference); // we just need the angle of that vector AssignCommand(oPC, SetCameraFacing(fDirection, fDistance, fPitch, nTransitionType)); } // Set camera facing of all players in oPC's party to point in direction of oTarget at the distance and pitch indicated. void SetCameraFacingPointParty(object oPC, object oTarget, float fDistance = -1.0, float fPitch = -1.0, int nTransitionType = CAMERA_TRANSITION_TYPE_SNAP) { object oPartyMember = GetFirstFactionMember(oPC, TRUE); // only look at PC's while(GetIsObjectValid(oPartyMember)) { SetCameraFacingPoint(oPartyMember, oTarget, fDistance, fPitch, nTransitionType); oPartyMember = GetNextFactionMember(oPC, TRUE); } } // ginc_death.nss /* NWN2 Knock Out/Wake Up death system functions */ // BMA-OEI 12/19/05 // BMA-OEI 12/22/05 added ResurrectParty(), ShowPartyDefeatedGUI() // BMA-OEI 1/16/06 removed comments, ForceRest() on respawn // BMA-OEI 2/28/06 modified KnockSelfOut(), ShowPartyDefeatedGUI() for death GUI // BMA-OEI 3/15/06 reduced wake up retry delay, added getisdead check to ShowPartyDefeatedGUI // BMA-OEI 4/17/06 cleaned up various functions, add support for GetIsCompanionPossessionBlocked() // BMA-OEI 8/22/06 -- Merged with kinc_death #include "ginc_debug" #include "x0_i0_henchman" const string GUI_DEATH = "SCREEN_PARTY_DEATH"; const string GUI_DEATH_WAIT_FOR_HELP = "BUTTON_WAIT_FOR_HELP"; const string GUI_DEATH_RESPAWN = "BUTTON_RESPAWN"; const string GUI_DEATH_LOAD_GAME = "BUTTON_LOAD_GAME"; const string GUI_DEATH_HIDDEN = "SCREEN_HIDDEN_DEATH"; const float KNOCKOUT_WAKE_UP_DELAY = 3.0f; // Delay between AttemptToWakeUpCreature() const float KNOCKOUT_WAKE_UP_SAFE_DISTANCE = 15.0f; // Hostiles within distance prevent WakeUp() const string KNOCKOUT_POPUP_DISPLAYED = "__bKnockOutPopUpDisplayed"; // Set if Death Screen is visible const int KNOCKOUT_CRYFORHELP = 183382; // StringRef for "... groan ..." //********************************************************* // FUNCTION PROTOTYPES //********************************************************* // Determine if oMember is a party member (either a PC, owned by a PC, or a roster member) int GetIsPartyMember( object oMember=OBJECT_SELF ); // Determine if oMember's faction has at least one member that is in combat // - bPartyOnly: If TRUE, only check members that are PC, owned by a PC, or a roster member int GetIsFactionInCombat( object oMember=OBJECT_SELF, int bPartyOnly=TRUE ); // Determine if oMember's faction has at least one member that is valid // - bPartyOnly: If TRUE, only check members that are PC, owned by a PC, or a roster member // - bNotDying: If TRUE, member must additionally be not dying ( HP>0 ) int GetIsFactionValid( object oMember=OBJECT_SELF, int bPartyOnly=TRUE, int bNotDying=TRUE ); // Determine if oObject can be possessed by oPossessor (owned char or an unblocked companion) int GetIsObjectPossessible( object oPossessor, object oObject ); // Determine if there is at least one object that can be validly possessed by oPartyMember int GetIsPartyPossessible( object oPartyMember=OBJECT_SELF ); // Determine if oPC is the host of the game int GetIsPCHost( object oPC ); // Determine if it is safe for oCreature to wake up // ( faction not in combat, no hostile creatures nearby, at least one member alive ) int GetIsSafeToWakeUp( object oCreature=OBJECT_SELF ); // Full resurrection, no penalty void ResurrectCreature( object oCreature ); // Resurrect entire faction ( PC party ) void ResurrectFaction( object oFactionMember ); // Go unconscious, queue AttemptToWakeUpCreature() void KnockOutCreature( object oCreature ); // Random audio/visual feedback for knock out void VoiceCryForHelp( object oCreature ); // Recursive function to Wake Up, Show and Hide Death Pop-up void AttemptToWakeUpCreature( object oCreature ); // Get Up after KnockOut void WakeUpCreature( object oCreature ); // Determine if Death screen is visible int GetIsDeathPopUpDisplayed( object oPC=OBJECT_SELF ); // Set var to identify Death screen as visible void SetIsDeathPopUpDisplayed( object oPC, int bDisplayed ); // Show appropriate Death screen for Single & Multiplayer void ShowProperDeathScreen( object oPC ); // Hide & Reset Death-related GUI screens void RemoveDeathScreens( object oPC=OBJECT_SELF ); // Displays Death Screen to oPC // - bModal: T/F, Display window modally // - bRespawn: T/F, Enables Respawn button // - bLoadGame: T/F, Enables Load Game button // - bWaitForHelp: T/F, Enables Wait For Help button void ShowDeathScreen( object oPC, int bModal=TRUE, int bRespawn=FALSE, int bLoadGame=FALSE, int bWaitForHelp=FALSE ); // Hides Death Screen for oPC void HideDeathScreen( object oPC ); // Displays Hidden Death Screen ( full screen button ) to oPC void ShowHiddenDeathScreen( object oPC ); // Hides Hidden Death Screen for oPC void HideHiddenDeathScreen( object oPC ); //********************************************************* // FUNCTION DEFINITIONS //********************************************************* // Determine if oMember is a party member (either a PC, owned by a PC, or a roster member) int GetIsPartyMember( object oMember=OBJECT_SELF ) { return ( GetIsPC( oMember ) || GetIsOwnedByPlayer( oMember ) || GetIsRosterMember( oMember ) ); } // Determine if oMember's faction has at least one member that is in combat // - bPartyOnly: If TRUE, only check members that are PC, owned by a PC, or a roster member int GetIsFactionInCombat( object oMember=OBJECT_SELF, int bPartyOnly=TRUE ) { object oTemp = GetFirstFactionMember( oMember, FALSE ); // For each faction member while ( GetIsObjectValid( oTemp ) == TRUE ) { // Check if they are in combat if ( GetIsInCombat( oTemp ) == TRUE ) { // They are, but do we care? if ( ( bPartyOnly == FALSE ) || ( GetIsPartyMember(oTemp) == TRUE ) ) { return ( TRUE ); } } // Check next faction member oTemp = GetNextFactionMember( oMember, FALSE ); } return ( FALSE ); } // Determine if oMember's faction has at least one member that is valid // - bPartyOnly: If TRUE, only check members that are PC, owned by a PC, or a roster member // - bNotDying: If TRUE, member must additionally be not dying ( HP>0 ) int GetIsFactionValid( object oMember=OBJECT_SELF, int bPartyOnly=TRUE, int bNotDying=TRUE ) { object oTemp = GetFirstFactionMember( oMember, FALSE ); // For each faction member while ( GetIsObjectValid( oTemp ) == TRUE ) { // Check if we only want party members if ( bPartyOnly == TRUE ) { // Are they in the party? if ( GetIsPartyMember( oTemp ) == TRUE ) { // Check if they must be alive if ( ( bNotDying == FALSE ) || ( GetIsDead(oTemp) == FALSE ) ) { return ( TRUE ); } } } else { // Check if they must be alive if ( ( bNotDying == FALSE ) || ( GetIsDead(oTemp) == FALSE ) ) { return ( TRUE ); } } // Check next faction member oTemp = GetNextFactionMember( oMember, FALSE ); } return ( FALSE ); } // Determine if oObject can be possessed by oPossessor (owned char or an unblocked companion) // Assumes PC faction int GetIsObjectPossessible( object oPossessor, object oObject ) { if ( ( GetOwnedCharacter( oPossessor) == oObject ) || ( ( GetIsRosterMember( oObject ) == TRUE ) && ( GetIsCompanionPossessionBlocked( oObject ) == FALSE ) ) ) { return ( TRUE ); } return ( FALSE ); } // Determine if there is at least one object that can be validly possessed by oPartyMember int GetIsPartyPossessible( object oPartyMember=OBJECT_SELF ) { object oMember = GetFirstFactionMember( oPartyMember, FALSE ); while ( GetIsObjectValid( oMember ) == TRUE ) { // If oMember is not dead, not possessed, and possessible by oPartyMember if ( GetIsDead( oMember ) == FALSE ) if ( GetIsPC( oMember ) == FALSE ) if ( GetIsObjectPossessible( oPartyMember, oMember ) == TRUE ) return ( TRUE ); oMember = GetNextFactionMember( oPartyMember, FALSE ); } return ( FALSE ); } int GetIsPCHost( object oPC ) { string sIP = GetPCIPAddress( oPC ); return ( sIP == "127.0.0.1" ); } // Determine if it is "safe" for oCreature to wake up // ( at least one PC or possessible companion alive, party not in combat, and no hostiles nearby ) int GetIsSafeToWakeUp( object oCreature=OBJECT_SELF ) { int bPartyAlive = FALSE; // For each faction member object oFM = GetFirstFactionMember( oCreature, FALSE ); while ( GetIsObjectValid(oFM) == TRUE ) { if ( GetIsDead(oFM) == FALSE ) { if ( ( GetIsOwnedByPlayer(oFM) == TRUE ) || ( ( GetIsRosterMember(oFM) == TRUE ) && ( GetIsCompanionPossessionBlocked(oFM) == FALSE ) ) ) { if ( GetIsInCombat(oFM) == FALSE ) { // At least one member alive and not in combat bPartyAlive = TRUE; } else { // "safe" conditions failed return ( FALSE ); } } } oFM = GetNextFactionMember( oCreature, FALSE ); } // Check if at least one member is alive and not in combat if ( bPartyAlive == FALSE ) { return ( FALSE ); } // Nearest valid, living, hostile, non-scripthidden creature object oHostile = GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oCreature, 1 ); if ( ( GetIsObjectValid( oHostile ) == TRUE ) && ( LineOfSightObject( oCreature, oHostile ) == TRUE ) && ( GetDistanceBetween( oCreature, oHostile ) < KNOCKOUT_WAKE_UP_SAFE_DISTANCE ) ) { return ( FALSE ); } else { // It's safe enough return ( TRUE ); } } // Full resurrection, no penalty void ResurrectCreature( object oCreature ) { ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectResurrection(), oCreature ); ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_G), oCreature ); AssignCommand( oCreature, ForceRest(oCreature) ); } // Resurrect entire faction ( PC party ) void ResurrectFaction( object oFactionMember ) { object oFM = GetFirstFactionMember( oFactionMember, FALSE ); while ( GetIsObjectValid(oFM) == TRUE ) { ResurrectCreature( oFM ); oFM = GetNextFactionMember( oFactionMember, FALSE ); } } // Go unconscious, queue AttemptToWakeUpCreature() void KnockOutCreature( object oCreature ) { AssignCommand( oCreature, SetCommandable(TRUE) ); AssignCommand( oCreature, ClearAllActions(TRUE) ); AssignCommand( oCreature, DelayCommand( KNOCKOUT_WAKE_UP_DELAY, AttemptToWakeUpCreature(oCreature) ) ); } // Random audio/visual feedback for knock out void VoiceCryForHelp( object oCreature ) { int nCry = d3(); switch ( nCry ) { case 1: nCry = VOICE_CHAT_PAIN1; break; case 2: nCry = VOICE_CHAT_PAIN2; break; default: nCry = VOICE_CHAT_PAIN3; } AssignCommand( oCreature, PlayVoiceChat( nCry, oCreature ) ); AssignCommand( oCreature, SpeakString( GetStringByStrRef( KNOCKOUT_CRYFORHELP ), TALKVOLUME_TALK ) ); } // Recursive function to Wake Up, Show and Hide Death Pop-up void AttemptToWakeUpCreature( object oCreature ) { //PrintString( "ginc_death: " + GetName(oCreature) + " executing AttemptToWakeUpCreature()" ); // Abort if oCreature is no longer dead if ( GetIsDead(oCreature) == FALSE ) { //PrintString( "** ginc_death: " + GetName(oCreature) + " is no longer dead (" + IntToString(GetCurrentHitPoints(oCreature)) + " HP)" ); RemoveDeathScreens( oCreature ); return; } // Check if it's safe to wake up if ( GetIsSafeToWakeUp(oCreature) == TRUE ) { //PrintString( "** ginc_death: " + GetName(oCreature) + " is waking up" ); WakeUpCreature( oCreature ); RemoveDeathScreens( oCreature ); return; } // Check if there are any members left for PC to possess if ( GetIsPC(oCreature) == TRUE ) { if ( GetIsDeathPopUpDisplayed(oCreature) == FALSE ) { if ( GetIsPartyPossessible(oCreature) == FALSE ) { //PrintString( "** ginc_death: " + GetName(oCreature) + "'s party wiped. displaying death screen" ); ShowProperDeathScreen( oCreature ); } } } // BMA-OEI 8/15/06 -- Knock out feedback if ( d6() == 1 ) { //PrintString( "** ginc_death: " + GetName(oCreature) + " cries for help" ); VoiceCryForHelp( oCreature ); } //PrintString( "** ginc_death: " + GetName(oCreature) + " still dead. next AttemptToWakeUpCreature() in 3s" ); DelayCommand( KNOCKOUT_WAKE_UP_DELAY, AttemptToWakeUpCreature(oCreature) ); } // Get Up after KnockOut void WakeUpCreature( object oCreature ) { //RemoveEffects( oCreature ); ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectResurrection(), oCreature ); ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_S), oCreature ); event eRes = EventSpellCastAt( oCreature, SPELL_RESURRECTION, FALSE ); SignalEvent( oCreature, eRes ); } // Determine if Death screen is visible int GetIsDeathPopUpDisplayed( object oPC=OBJECT_SELF ) { return ( GetLocalInt( oPC, KNOCKOUT_POPUP_DISPLAYED ) ); } // Set var to identify Death screen as visible void SetIsDeathPopUpDisplayed( object oPC, int bDisplayed ) { SetLocalInt( oPC, KNOCKOUT_POPUP_DISPLAYED, bDisplayed ); } // Show appropriate Death screen for Single & Multiplayer void ShowProperDeathScreen( object oPC=OBJECT_SELF ) { // Force PC into original character oPC = SetOwnersControlledCompanion( oPC ); int bWaitForHelp = FALSE; int bRespawn = FALSE; int bLoadGame = FALSE; int bMultiplayer = !GetIsSinglePlayer(); // Wait For Help, Respawn options only available in MP if ( bMultiplayer == TRUE ) { bWaitForHelp = TRUE; bRespawn = TRUE; bLoadGame = GetIsPCHost(oPC); } else { bWaitForHelp = FALSE; bRespawn = FALSE; bLoadGame = TRUE; } ShowDeathScreen( oPC, TRUE, bRespawn, bLoadGame, bWaitForHelp ); SetIsDeathPopUpDisplayed( oPC, TRUE ); } // Hide & Reset Death-related GUI screens void RemoveDeathScreens( object oPC=OBJECT_SELF ) { HideDeathScreen( oPC ); HideHiddenDeathScreen( oPC ); SetIsDeathPopUpDisplayed( oPC, FALSE ); } // Displays Death Screen to oPC // - bModal: T/F, Display window modally // - bRespawn: T/F, Enables Respawn button // - bLoadGame: T/F, Enables Load Game button // - bWaitForHelp: T/F, Enables Wait For Help button void ShowDeathScreen( object oPC, int bModal=TRUE, int bRespawn=FALSE, int bLoadGame=FALSE, int bWaitForHelp=FALSE ) { SetGUIObjectHidden( oPC, GUI_DEATH, GUI_DEATH_WAIT_FOR_HELP, !bWaitForHelp ); SetGUIObjectHidden( oPC, GUI_DEATH, GUI_DEATH_RESPAWN, !bRespawn ); SetGUIObjectDisabled( oPC, GUI_DEATH, GUI_DEATH_LOAD_GAME, !bLoadGame ); DisplayGuiScreen( oPC, GUI_DEATH, bModal ); } // Hides Death Screen for oPC void HideDeathScreen( object oPC ) { CloseGUIScreen( oPC, GUI_DEATH ); } // Displays Hidden Death Screen ( full screen button ) to oPC void ShowHiddenDeathScreen( object oPC ) { DisplayGuiScreen( oPC, GUI_DEATH_HIDDEN, FALSE ); } // Hides Hidden Death Screen for oPC void HideHiddenDeathScreen( object oPC ) { CloseGUIScreen( oPC, GUI_DEATH_HIDDEN ); } // ginc_debug /* Debug functions */ // ChazM 9/22/05 // BMA-OEI 9/27/05 tweak default x,y, DebugMessage now prefixes "Debug: " // ChazM 10/02/05 added more colors, added MessageLine() and DebugMessageLine() // BMA-OEI 10/17/05 added PrettyPostString(), PrettyDebug(), PrettyError(), PrettyMessage() // ChazM 10/18/05 added Backdrop(), modified Message(), PrettyPostString(), added some constants // BMA-OEI 10/19/05 fixed backdrop problem in Message() // BMA-OEI 12/19/05 added GetFirstPCInFaction() // BMA-OEI 1/23/06 updated to use GetFirstPC(FALSE) // EPF 1/25/06 -- removing the color constants -- they've been added to nwscript.nss. // BMA-OEI 1/25/06 adding POST_ colors // ChazM 1/26/06 - modified GetFirstPCInFaction() to no longer use functions that affect the First/Next pointer. //void main(){} const int POST_COLOR_RED = 4294901760; // FFFF0000 const int POST_COLOR_GREEN = 4278255360; // FF00FF00 const int POST_COLOR_BLUE = 4278190335; // FF0000FF const int POST_COLOR_WHITE = 4294967295; // FFFFFFFF const int POST_COLOR_BLACK = 4278190080; // FF000000 const int POST_COLOR_OFFSET = 4278190080; // FF000000 int POST_COLOR_RED_DARK = POST_COLOR_OFFSET + FOG_COLOR_RED_DARK; int POST_COLOR_GREEN_DARK = POST_COLOR_OFFSET + FOG_COLOR_GREEN_DARK; int POST_COLOR_BLUE_DARK = POST_COLOR_OFFSET + FOG_COLOR_BLUE_DARK; int POST_COLOR_GREY = POST_COLOR_OFFSET + FOG_COLOR_GREY; int POST_COLOR_YELLOW = POST_COLOR_OFFSET + FOG_COLOR_YELLOW; int POST_COLOR_YELLOW_DARK = POST_COLOR_OFFSET + FOG_COLOR_YELLOW_DARK; int POST_COLOR_CYAN = POST_COLOR_OFFSET + FOG_COLOR_CYAN; int POST_COLOR_MAGENTA = POST_COLOR_OFFSET + FOG_COLOR_MAGENTA; int POST_COLOR_ORANGE = POST_COLOR_OFFSET + FOG_COLOR_ORANGE; int POST_COLOR_ORANGE_DARK = POST_COLOR_OFFSET + FOG_COLOR_ORANGE_DARK; int POST_COLOR_BROWN = POST_COLOR_OFFSET + FOG_COLOR_BROWN; int POST_COLOR_BROWN_DARK = POST_COLOR_OFFSET + FOG_COLOR_BROWN_DARK; const int POST_COLOR_DEBUG = 4291624857; // FFCCFF99 Pale Dull Spring const int POST_COLOR_ERROR = 4294941132; // FFFF99CC Pale Dull Pink const int LINE_SIZE = 13; const int PRETTY_LINE_WRAP = 42; const int PRETTY_X_OFFSET = 13; const int PRETTY_Y_OFFSET = 13; const float PRETTY_DURATION = 13.0f; string PRETTY_LINE_COUNT_VAR = "00_nPrettyLineCount"; const float DURATION_NORMAL = 10.0f; const float DURATION_LONG = 30.0f; //------------------------------------------------- // Function Prototypes //------------------------------------------------- object GetFirstPCInFaction(object oPC); void Message(string sMessage, int nX=50, int nY=50, float fDuration=DURATION_NORMAL, int nColor=POST_COLOR_GREEN, int nBackdropColor=POST_COLOR_BLACK); void ErrorMessage(string sMessage, int nX=60, int nY=60, float fDuration=DURATION_LONG, int nColor=POST_COLOR_RED); void DebugMessage(string sMessage, int nX=70, int nY=70, float fDuration=DURATION_NORMAL, int nColor=POST_COLOR_BLUE); void OldFunctionMessage(string sOldFunctionName, string sNewFunctionName); void MessageLine(int nLine, string sMessage, int nX=50, float fDuration=DURATION_LONG, int nColor=POST_COLOR_GREEN); void DebugMessageLine(int nLine, string sMessage, int nX=50, float fDuration=DURATION_LONG, int nColor=POST_COLOR_BLUE); void PrettyPostString(object oTarget, string sMessage, float fDuration, int nColor=POST_COLOR_WHITE); void PrettyDebug(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_DEBUG); void PrettyError(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_ERROR); void PrettyMessage(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_WHITE); void Backdrop(object oTarget, string sMessage, int nX, int nY, float fDuration, int nColor=POST_COLOR_BLACK); //------------------------------------------------- // Function Definitions //------------------------------------------------- // Return first player object controlled by a player object GetFirstPCInFaction(object oPC) { object oRet = oPC; if (!GetIsPC(oRet)) // if not player controlled { oRet = GetPCSpeaker(); if (!GetIsPC(oRet)) { // this is problematic as it resets the flag used for some GetFirst* functions oRet = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_CONTROLLED, oPC); } } return (oRet); } // Post a message w/ a backdrop to make it more readable. void Message(string sMessage, int nX=50, int nY=50, float fDuration=DURATION_NORMAL, int nColor=POST_COLOR_GREEN, int nBackdropColor=POST_COLOR_BLACK) { object oPC = GetFirstPC(FALSE); Backdrop(oPC, sMessage, nX, nY, fDuration, nBackdropColor); DebugPostString(oPC, sMessage, nX, nY, fDuration, nColor); PrintString(sMessage); } // Post an error meesage - these stay up for a while and are in Red void ErrorMessage(string sMessage, int nX=60, int nY=60, float fDuration=DURATION_LONG, int nColor=POST_COLOR_RED) { sMessage = "Error: " + sMessage; Message(sMessage, nX, nY, fDuration, nColor); } // messages in blue for debug purposes only. void DebugMessage(string sMessage, int nX=70, int nY=70, float fDuration=DURATION_NORMAL, int nColor=POST_COLOR_BLUE) { sMessage = "Debug: " + sMessage; Message(sMessage, nX, nY, fDuration, nColor); } // a specialized error message for phasing out old stuff void OldFunctionMessage(string sOldFunctionName, string sNewFunctionName) { string sMessage = "Function '" + sOldFunctionName + "' is obsolete and should be replaced with '" + sNewFunctionName; ErrorMessage(sMessage); } // Message posted at a specific line number. Message stays longer by default since there are probably multiple lines to read void MessageLine(int nLine, string sMessage, int nX=50, float fDuration=DURATION_LONG, int nColor=POST_COLOR_GREEN) { int nY = nLine * LINE_SIZE; Message(sMessage, nX, nY, fDuration, nColor); } // messages line in blue for debug purposes only. void DebugMessageLine(int nLine, string sMessage, int nX=50, float fDuration=DURATION_LONG, int nColor=POST_COLOR_BLUE) { int nY = nLine * LINE_SIZE; Message(sMessage, nX, nY, fDuration, nColor); } // Post message with drop-shadow and print to log void PrettyPostString(object oTarget, string sMessage, float fDuration, int nColor=POST_COLOR_WHITE) { int nX = PRETTY_X_OFFSET; int nLineOffset = GetGlobalInt(PRETTY_LINE_COUNT_VAR); int nY = PRETTY_Y_OFFSET + (nLineOffset * LINE_SIZE); Backdrop(oTarget, sMessage, nX, nY, fDuration, POST_COLOR_BLACK); DebugPostString(oTarget, sMessage, nX, nY, fDuration, nColor); PrintString(sMessage); nLineOffset = (nLineOffset + 1) % PRETTY_LINE_WRAP; SetGlobalInt(PRETTY_LINE_COUNT_VAR, nLineOffset); } // Pretty post message in debug color void PrettyDebug(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_DEBUG) { object oPC = GetFirstPC(FALSE); PrettyPostString(oPC, sMessage, fDuration, nColor); } // Pretty post message in error color void PrettyError(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_ERROR) { object oPC = GetFirstPC(FALSE); PrettyPostString(oPC, sMessage, fDuration, nColor); } // Pretty post message void PrettyMessage(string sMessage, float fDuration=PRETTY_DURATION, int nColor=POST_COLOR_WHITE) { object oPC = GetFirstPC(FALSE); PrettyPostString(oPC, sMessage, fDuration, nColor); } // Post message with drop-shadow and print to log void Backdrop(object oTarget, string sMessage, int nX, int nY, float fDuration, int nColor=POST_COLOR_BLACK) { DebugPostString(oTarget, sMessage, nX - 1, nY - 1, fDuration, nColor); DebugPostString(oTarget, sMessage, nX + 1, nY - 1, fDuration, nColor); DebugPostString(oTarget, sMessage, nX + 1, nY + 1, fDuration, nColor); DebugPostString(oTarget, sMessage, nX - 1, nY + 1, fDuration, nColor); } // ginc_effect /* Effects related constants and functions Note that many of these effects are temporary. I would not count on the SP_ effects and TESTSEF effects in particular to persist until ship time, so keep that in mind. -EPF */ // ChazM 10/03/05 // EPF 10/3/05 // ChazM 10/03/05 added CreateBeam(), VoidCreateBeam(), changed include file // ChazM 10/04/05 added Note on SEF's and the nBodyPart param // BMA-OEI 7/04/06 -- Added GetHasEffectType(), RemoveEffectByType() #include "ginc_param_const" //void main (){} //For reference, here are the prototypes for the related functions in nwscript.nss: /* //RWT-OEI 05/31/05 //This function creates a Special Effects File effect that can //then be applied to an object or a location //For effects that just need a single location (or source object), //such as particle emitters, the source loc or object comes from //using AttachEffectToObject and AttachEffectToLocation //For Point-to-Point effects, like beams and lightning, oTarget //is the target object for the other end of the effect. If oTarget //is OBJECT_INVALID, then the position located in vTargetPosition //is used instead. effect EffectNWN2SpecialEffectFile( string sFileName, object oTarget=OBJECT_INVALID, vector vTargetPosition=[0.0,0.0,0.0] ); //RWT-OEI 06/07/05 //This function removes 1 instance of a SEF from an object. Since //an object can only have 1 instance of a specific SEF running on it //at once, this should effectively remove 'all' instances of the //specified SEF from the object void RemoveSEFFromObject( object oObject, string sSEFName ); */ /* Note on SEF's and the nBodyPart param: The nBodyPart piece has been moved to the .SEF file. The SEF file can be used to specify which attachment points the beam should connect to on both the source and the target. */ //Durations below this number specified in the effect applying functions will be treated as 0, //which we take to mean you want to apply an effect permanently const float MY_EPSILON = 0.001; const string BLOODSPURT = "bloodspurt.sef"; const string FX_ALTARGEN = "fx_altargen.sef"; const string FX_BLACK_COULD = "fx_black_cloud.sef"; const string FX_CANDLE = "fx_candle.sef"; const string FX_DUST = "fx_dust.sef"; const string FX_FIREFLIES = "fx_fireflies.sef"; const string FX_FIREPLACE = "fx_fireplace.sef"; const string FX_FIRE_LG = "fx_fire_lg.sef"; const string FX_FIRE_LG_BLUR = "fx_fire_lg_blur.sef"; const string FX_FIRE_SMOKE = "fx_fire_smoke.sef"; const string FX_FOG_LG = "fx_fog_lg.sef"; const string FX_LAMPGLOW = "fx_lampglow.sef"; const string FX_LOOTBAG = "fx_lootbag.sef"; const string FX_SPLASH = "fx_splash.sef"; const string FX_SPLASH2 = "fx_splash2.sef"; const string FX_TORCH_BLUE = "fx_torch_blue.sef"; const string FX_TORCHGLOW = "fx_torchglow.sef"; const string FX_VOID = "fx_void.sef"; const string SP_ATK_MISSILE = "sp_atk_missile.sef"; const string SP_BLESS = "sp_bless.sef"; const string SP_CURE_CRITICAL = "sp_cure_critical.sef"; const string SP_CURE_LIGHT = "sp_cure_light.sef"; const string SP_FIREBALL = "sp_fireball.sef"; const string SP_MAGICMISSILE = "sp_magicmissile.sef"; const string SP_RAYFROST = "sp_rayfrost.sef"; //** FUNCTION DECLARATIONS ** // SEF effect functions //** For all below functions, Duration of 0 means effect is permanent. ** void ApplySEFToLocation(string sEffectFile, location lLoc, float fDuration = 0.f); void ApplySEFToObject(string sEffectFile, object oTarget, float fDuration = 0.f); void ApplySEFToObjectByTag(string sEffectFile, string sTag, float fDuration = 0.f); void ApplySEFToWP(string sEffectFile, string sWPTag, float fDuration = 0.f); //SEF goes to all WPs of tag sWPTag void ApplySEFToWPs(string sEffectFile, string sWPTag, float fDuration = 0.f); void RemoveSEFFromWP(string sEffectFile, string sWPTag ); //SEF removed from all WPs of tag sWPTag void RemoveSEFFromWPs(string sEffectFile, string sWPTag ); // Other effect functions effect CreateBeam(int iBeamVisualEffect, object oSource, object oTarget, int nDurationType=DURATION_TYPE_PERMANENT, float fDuration = 0.0f, int nBodyPart = BODY_NODE_CHEST, int bMissEffect = FALSE); void VoidCreateBeam(int iBeamVisualEffect, object oSource, object oTarget, int nDurationType=DURATION_TYPE_PERMANENT, float fDuration = 0.0f, int nBodyPart = BODY_NODE_CHEST, int bMissEffect = FALSE); // Return TRUE, if oObject is affected by effect type nEffectType int GetHasEffectType( object oObject, int nEffectType ); // Removes all effects from oObject matching effect type nEffectType // Returns number of matching effects removed int RemoveEffectsByType( object oObject, int nEffectType ); void ApplySEFToLocation(string sEffectFile, location lLoc, float fDuration = 0.f) { if(fDuration < MY_EPSILON) { ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectNWN2SpecialEffectFile(sEffectFile), lLoc); } else { ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectNWN2SpecialEffectFile(sEffectFile), lLoc, fDuration); } } void ApplySEFToObject(string sEffectFile, object oTarget, float fDuration = 0.f) { if(fDuration < MY_EPSILON) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectNWN2SpecialEffectFile(sEffectFile), oTarget); } else { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNWN2SpecialEffectFile(sEffectFile), oTarget, fDuration); } } void ApplySEFToObjectByTag(string sEffectFile, string sTag, float fDuration = 0.f) { if(fDuration < MY_EPSILON) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sTag)); } else { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sTag), fDuration); } } void ApplySEFToWP(string sEffectFile, string sWPTag, float fDuration = 0.f) { if(fDuration < MY_EPSILON) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sWPTag)); } else { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sWPTag), fDuration); } } void ApplySEFToWPs(string sEffectFile, string sWPTag, float fDuration = 0.f) { object oWP = GetObjectByTag(sWPTag); int i = 1; while(GetIsObjectValid(oWP)) { if(fDuration < MY_EPSILON) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sWPTag)); } else { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNWN2SpecialEffectFile(sEffectFile), GetTarget(sWPTag), fDuration); } oWP = GetObjectByTag(sWPTag,i); i++; } } void RemoveSEFFromWP(string sEffectFile, string sWPTag ) { RemoveSEFFromObject( GetTarget(sWPTag), sEffectFile ); } void RemoveSEFFromWPs(string sEffectFile, string sWPTag ) { object oWP = GetObjectByTag(sWPTag); int i = 1; while(GetIsObjectValid(oWP)) { RemoveSEFFromObject(oWP, sEffectFile); oWP = GetObjectByTag(sWPTag,i); i++; } } // create a beam between two objects effect CreateBeam(int iBeamVisualEffect, object oSource, object oTarget, int nDurationType=DURATION_TYPE_PERMANENT, float fDuration = 0.0f, int nBodyPart = BODY_NODE_CHEST, int bMissEffect = FALSE) { effect eBeam = EffectBeam(iBeamVisualEffect, oSource, nBodyPart); ApplyEffectToObject(nDurationType, eBeam, oTarget, fDuration); return (eBeam); } void VoidCreateBeam(int iBeamVisualEffect, object oSource, object oTarget, int nDurationType=DURATION_TYPE_PERMANENT, float fDuration = 0.0f, int nBodyPart = BODY_NODE_CHEST, int bMissEffect = FALSE) { CreateBeam(iBeamVisualEffect, oSource, oTarget, nDurationType, fDuration, nBodyPart, bMissEffect); } // Return TRUE, if oObject is affected by effect type nEffectType int GetHasEffectType( object oObject, int nEffectType ) { effect eEffect = GetFirstEffect( oObject ); while ( GetIsEffectValid(eEffect) == TRUE ) { if ( GetEffectType(eEffect) == nEffectType ) { return ( TRUE ); } eEffect = GetNextEffect( oObject ); } return ( FALSE ); } // Removes all effects from oObject matching effect type nEffectType // Returns number of matching effects removed int RemoveEffectsByType( object oObject, int nEffectType ) { int nCount = 0; effect eEffect = GetFirstEffect( oObject ); while ( GetIsEffectValid(eEffect) == TRUE ) { if ( GetEffectType(eEffect) == nEffectType ) { nCount = nCount + 1; RemoveEffect( oObject, eEffect ); eEffect = GetFirstEffect( oObject ); } else { eEffect = GetNextEffect( oObject ); } } return ( nCount ); } // ginc_event_handlers /* event handler related */ // ChazM 12/21/05 // ChazM 4/30/06 - Added EventsCleared flag and SafeClearEventHandlers(), SafeRestoreEventHandlers(), added support for remainder of object types // ChazM 6/16/06 - fixed GetNumScripts(), added ReportEventHandlers() // // void main() {} const string EVENTS_CLEARED_FLAG = "EH_CLEARED"; const string EVENTS_SAVE_PREFIX = "EH_SAVE"; #include "ginc_debug" int GetEventsClearedFlag(object oObject) { int bEventsCleared = GetLocalInt(oObject, EVENTS_CLEARED_FLAG); return (bEventsCleared); } void SetEventsClearedFlag(object oObject, int bFlag) { SetLocalInt(oObject, EVENTS_CLEARED_FLAG, bFlag); } /* int OBJECT_TYPE_CREATURE = 1; int OBJECT_TYPE_ITEM = 2; int OBJECT_TYPE_TRIGGER = 4; int OBJECT_TYPE_DOOR = 8; int OBJECT_TYPE_AREA_OF_EFFECT = 16; int OBJECT_TYPE_WAYPOINT = 32; int OBJECT_TYPE_PLACEABLE = 64; int OBJECT_TYPE_STORE = 128; int OBJECT_TYPE_ENCOUNTER = 256; int OBJECT_TYPE_LIGHT = 512; int OBJECT_TYPE_PLACED_EFFECT = 1024; */ int GetNumScripts(object oObject) { int iObjectType = GetObjectType(oObject); // doesn't appear to have a value for areas and modules int iNumScripts = 0; // see nwscript.nss for list of script event handlers switch (iObjectType) { case OBJECT_TYPE_CREATURE: iNumScripts = 13; break; case OBJECT_TYPE_ITEM: // items don't have scripts iNumScripts = 0; break; case OBJECT_TYPE_TRIGGER: iNumScripts = 7; break; case OBJECT_TYPE_DOOR: iNumScripts = 15; break; case OBJECT_TYPE_AREA_OF_EFFECT: iNumScripts = 4; break; case OBJECT_TYPE_WAYPOINT: iNumScripts = 0; break; case OBJECT_TYPE_PLACEABLE: iNumScripts = 15; break; case OBJECT_TYPE_STORE: iNumScripts = 2; break; case OBJECT_TYPE_ENCOUNTER: iNumScripts = 5; break; case OBJECT_TYPE_LIGHT: iNumScripts = 0; break; case OBJECT_TYPE_PLACED_EFFECT: iNumScripts = 0; break; } return (iNumScripts); } void SaveEventHandlers(object oObject) { string sEventHandler; string sVarName; int iNumScripts = GetNumScripts(oObject); int i; for (i=0; i 0 // BMA-OEI 12/01/05 updated GroupGetNumValidObjects(), GetIsGroupValid() parameter check IsDead // EPF 12/5/05 -- Added GroupOnDeathSetJournalEntry() // EPF 1/12/06 -- added GroupSetSemicircleFormation and support for a new Semicircle formation. // EPF 1/13/06 -- Fixed an off-by-one error in GroupAddNearestTag(). // EPF 1/30/06 -- missed a spot in the last fix, so GroupAddNearestTag was adding one too many. Fixed. // EPF 1/30/06 -- GroupAddTag() has a completely different off-by-one error. Fixing. // DBR 2/01/06 -- Added GetGroupName(), for retrieving the group that a creature is in (wrapper function) // BMA-OEI 2/8/06 -- Added bFadeOut param to GroupOnDeathConversation() // BMA-OEI 2/14/06 -- Removed bFadeOut param // EPF 2/18/06 -- Added GroupSetScriptHidden(). // BMA-OEI 2/27/06 -- Added GroupFleeToExit() // BMA-OEI 2/27/06 -- Added GroupResurrect() // ChazM 3/16/06 modified SpawnCreaturesInGroupAtWP(), modified AddToGroup() - no longer marked as old. // ChazM 4/19/06 Added GroupOnDeathExecuteCustomScript() // BMA-OEI 5/23/06 -- Added IncGroupNumKilled(), GetGroupNumKiled(), GROUP_VAR_NUM_KILLED // BMA-OEI 6/20/06 -- Added GroupSetIsDestroyable() // BMA-OEI 7/04/06 -- Added GetIsGroupDominated() // BMA-OEI 8/02/06 -- Update ResetGroup() to check if still in group // ChazM 9/21/06 -- added nw_i0_generic #include "ginc_actions" #include "ginc_effect" #include "ginc_utility" #include "x0_i0_petrify" #include "ginc_debug" #include "ginc_vars" #include "ginc_math" #include "nw_i0_generic" //#include "x0_i0_position" //#include "x0_i0_spawncond" //void main() {} // Public constants const int FORMATION_DEFAULT = 0; const int FORMATION_BMA = 1; const int FORMATION_HUDDLE_FACE_IN = 2; const int FORMATION_HUDDLE_FACE_OUT = 3; const int FORMATION_HUDDLE_FACE_FORWARD = 4; const int FORMATION_RECTANGLE = 5; const int FORMATION_NONE = 6; const int FORMATION_LINE = 7; const int FORMATION_SEMICIRCLE_FACE_OUT = 8; const int FORMATION_SEMICIRCLE_FACE_IN = 9; const int MOVE_WALK = 1; const int MOVE_RUN = 2; const int MOVE_JUMP = 3; const int MOVE_JUMP_INSTANT = 4; const int MOVE_FORCE_WALK = 5; const int MOVE_FORCE_RUN = 6; const int GROUP_LEADER_FIRST = -1; const int GROUP_LEADER_LAST = -2; const int GROUP_LEADER_EXCLUDE = -3; const string PARTY_GROUP_NAME = "theParty"; const int TYPE_INT = 1; const int TYPE_FLOAT = 2; const int TYPE_STRING = 3; // Private constants const string GROUP_VAR_NUM_KILLED = "NumKilled"; const string OBJ_GROUP_MY_GROUP = "MyGroup"; // var name stored on objects (so object can identify the group he's in) const string OBJ_GROUP_PREFIX = "_OG"; const string OBJ_GROUP_NUM = "_Num"; const string OBJ_GROUP_INDEX = "_Indx"; const string OBJ_GROUP_FORMATION_TYPE = "Fmn"; const string OBJ_GROUP_FORMATION_RADIUS = "Rad"; const string OBJ_GROUP_FORMATION_COLS = "Col"; const string OBJ_GROUP_FORMATION_SPACING = "Spc"; const string OBJ_GROUP_NOISE_START = "StN"; const string OBJ_GROUP_NOISE_FACING = "FcN"; const string OBJ_GROUP_NOISE_LOCATION = "LcN"; const float DEFAULT_SPACING = 1.8f; //------------------------------------------------- // Public function Prototypes //------------------------------------------------- void ResetGroup(string sGroupName); // Reset a group for re-use int IsGroupEmpty(string sGroupName); // used to see if the group already contains creatures in it. int GroupGetNumValidObjects(string sGroupName, int bIsDead=FALSE); // return number of valid creatures in group int GetIsGroupValid(string sGroupName, int bNotDying=FALSE); // check if group has any valid creatures in it string GetGroupName(object oMember); //Retrieves the group a creature is in // Return TRUE, if all remaining members are dominated int GetIsGroupDominated( string sGroupName ); // ********************** // *** Group creation *** // ********************** string GetPartyGroup(object oPC); // creates group for the party and returns name. void GroupAddMember(string sGroupName, object oMember, int bOverridePrevGroup=FALSE); void GroupAddFaction(string sGroupName, object oFactionMember, int nLeaderPos=GROUP_LEADER_FIRST, int bOverridePrevGroup=FALSE); void GroupAddTag(string sGroupName, string sTag, int iMax=20, int bOverridePrevGroup=FALSE); void GroupAddNearestTag(string sGroupName, string sTag, object oTarget=OBJECT_SELF, int iMax=20, int bOverridePrevGroup=FALSE); void GroupAddEncounter(string sGroupName, int bWander=2, int bOverridePrevGroup=FALSE); void GroupSpawnAtLocation(string sGroupName, string sTemplate, location lLocation, int nNum); void GroupSpawnAtWaypoint(string sGroupName, string sTemplate, string sWaypoint, int nNum); // *************************************** // *** Group Formation and Noise setup *** // *************************************** void GroupSetNoFormation(string sGroupName); // single base destination for group void GroupSetBMAFormation(string sGroupName, float fSpacing=DEFAULT_SPACING); // a staggered marching formation void GroupSetCircleFormation(string sGroupName, int iFacing=FORMATION_HUDDLE_FACE_IN , float fRadius=5.0f); // a circle or huddle formation void GroupSetSemicircleFormation(string sGroupName, int iFacing = FORMATION_SEMICIRCLE_FACE_OUT, float fRadius = 5.f); void GroupSetLineFormation(string sGroupName, float fSpacing=DEFAULT_SPACING); // single row formation, leader in middle void GroupSetRectangleFormation(string sGroupName, float fSpacing=1.8f, int nColumns=2); // a rectangular or single line formation void GroupSetNoise(string sGroupName, float fStartNoise=0.5f, float fFacingNoise=10.0f, float fLocationNoise=0.5f); // use to add noise to the group and make them appear less synchronized void GroupOnDeathBeginConversation(string sGroupName, string sTalkerTag, string sConversation); // use to have a convo begin after everyone in the group dies void GroupOnDeathSetLocalInt( string sGroupName, object oTargetObject, string sVariableName, int nNewValue ); // Used for setting a local integer on a target object upon the death of the specified group void GroupOnDeathSetLocalFloat( string sGroupName, object oTargetObject, string sVariableName, float fNewValue ); // Used for setting a local float on a target object upon the death of the specified group void GroupOnDeathSetLocalString( string sGroupName, object oTargetObject, string sVariableName, string sNewValue ); // Used for setting a local string on a target object upon the death of the specified group void GroupOnDeathExecuteCustomScript(string sGroupName, string sScriptName); // ********************* // *** Group Actions *** // ********************* void GroupForceMoveToLocation(string sGroupName, location lDestination, int bRun=FALSE, float fTimeout=30.0f); //void GroupForceMoveToObject(string sGroupName, string sObject, int bRun); void GroupMoveToFormationLocation(string sGroupName, location lDestination, int iMoveType=MOVE_WALK); // locomote a group to a specified location (formation and noise should be set first) void GroupMoveToWP(string sGroupName, string sWaypoint, int iMoveType=MOVE_WALK); // locomote a group to a specified waypoint (formation and noise should be set first) void GroupMoveToObject(string sGroupName, object oTarget, int iMoveType=MOVE_WALK); // locomote a group to a specified object (formation and noise should be set first) void GroupFleeToExit(string sGroupName, string sWaypoint, int iMoveType=MOVE_WALK); void GroupJumpToWP(string sGroupName, string sWaypoint); void GroupAttack(string sGroupName, object oTarget); void GroupClearAllActions(string sGroupName, int nClearCombatState = FALSE); void GroupPlayAnimation(string sGroupName, int nAnimation, float fStartNoise=1.0f, float fSpeedBase=1.0f, float fSpeedRange=1.0f, float fDurationSectondsBase=0.0f, float fDurationSectondsRange=0.0f); void GroupActionWait(string sGroupName, float fSeconds=0.0f); void GroupActionOrientToTag(string sGroupName, string sTag, int iOrientation=ORIENT_FACE_TARGET, int bIgnoreWait=FALSE); void GroupResurrect(string sGroupName, int bIgnoreWait=FALSE); void GroupSetLocalString (string sGroupName, string sVarName, string sValue); void GroupSetLocalObject (string sGroupName, string sVarName, object oValue); void GroupSetLocalInt (string sGroupName, string sVarName, int iValue); void GroupSetLocalFloat (string sGroupName, string sVarName, float fValue); void GroupSetSpawnInCondition(string sGroupName, int nCondition, int bValid=TRUE); void GroupWander(string sGroupName, int bValid = TRUE); void GroupActionForceExit(string sGroupName, string sWPTag = "WP_EXIT", int bRun=FALSE); // forces all in group to go to destination and then destroy self. void GroupChangeFaction(string sGroupName, string sTargetFactionMember); // Changes everyone in group to join faction of given creature void GroupChangeToStandardFaction(string sGroupName, int iFaction); // Changes everyone in group to join one of the standard factions void GroupActionMoveToObject(string sGroupName, object oTarget, int bRun=FALSE, float fRange=1.0f); // does action move to object for all in group (doesn't use formation/noise) void GroupAttackGroup(string sAttackerGroupName, string sAttackedGroupName); // have group attak targets in another group void GroupDetermineCombatRound(string sGroupName); void GroupSetFacingPoint(string sGroupName, vector vPoint); // assign SetFacingPoint(vPoint) to each member, no delay void DestroyObjectsInGroup(string sGroupName, float fDelay=0.0f); void GroupSetImmortal(string sGroupName, int bImmortal); void GroupSetPlotFlag(string sGroupName, int bPlotFlag); void GroupActionForceFollowObject(string sGroupName, object oMaster, float fFollowDistance = 5.0f); void GroupStartFollowLeader(string sGroupName, object oMaster, float fFollowDistance = 5.0f); void GroupStopFollowLeader(string sGroupName); void GroupGoHostile(string sGroupName); void GroupSurrenderToEnemies(string sGroupName); void GroupActionMoveAwayFromObject(string sGroupName, object oFleeFrom, int bRun = FALSE, float fMoveAwayRange = 40.0f); void GroupActionCastFakeSpellAtObject(string sGroupName, int nSpell, object oTarget, int nProjectilePathType = PROJECTILE_PATH_TYPE_DEFAULT); void GroupSignalEvent(string sGroupName, event eEvent); void GroupSetScriptHidden(string sGroupName, int bHidden = TRUE); int IncGroupNumKilled( string sGroupName ); int GetGroupNumKiled( string sGroupName ); void GroupSetIsDestroyable( string sGroupName, int bDestroyable, int bRaisable=TRUE, int bSelectableWhenDead=FALSE ); //------------------------------------------------- // Private function prototypes //------------------------------------------------- // Helper funcs //void SendDebugMessage(string sMessage); location GetWPLocation(string sWayPoint); // Prototypes - Group Base functions object GroupGetObjectIndex(string sGroupName, int iIndex); void GroupSetObjectIndex(string sGroupName, int iIndex, object oObject); void GroupDeleteObjectIndex(string sGroupName, int iIndex); int GroupGetNumObjects(string sGroupName); void GroupSetNumObjects(string sGroupName, int iNumObjects); int GroupGetCurrentIndex(string sGroupName); void GroupSetCurrentIndex(string sGroupName, int iIndex); object GroupGetCurrentObject(string sGroupName); int GroupIncrementIndex(string sGroupName); object GetFirstValidInGroupFromCurrent(string sGroupName); // return first valid object in group starting w/ current. object GetFirstInGroup(string sGroupName); object GetNextInGroup(string sGroupName); // add a new a creature to a group int InsertIntoGroup(string sGroupName, object oObject, int bOverridePrevGroup = FALSE); void SetGroupInt(string sGroupName, string sVarName, int iValue); int GetGroupInt(string sGroupName, string sVarName); void DeleteGroupInt(string sGroupName, string sVarName); void SetGroupFloat(string sGroupName, string sVarName, float fValue); float GetGroupFloat(string sGroupName, string sVarName); void DeleteGroupFloat(string sGroupName, string sVarName); void SetGroupString(string sGroupName, string sVarName, string sValue); string GetGroupString(string sGroupName, string sVarName); void DeleteGroupString(string sGroupName, string sVarName); void SetGroupObject( string sGroupName, string sVarName, object oValue ); object GetGroupObject( string sGroupName, string sVarName ); vector GetBMAFormationStartPosition(vector vPosition, int nIndex, float fSpacing, float fFacing); location GetBMALocation(location lToJumpTo, int nIndex, float fSpacing); location GetHuddleLocation(location lDestination, int iMemberIndex, int iNumObjects, float fRadius=10.0f, int iFaceType=FORMATION_HUDDLE_FACE_IN); location GetLineLocation(location lDestination, int iMemberIndex, float fSpacing); location GetRectangleLocation(location lDestination, int nMemberIndex, int nColumns, float fSpacing); // old versions of functions - don't use but kept for compatibility int AddToGroup(string sGroupName, object oObject); // add a new a creature to a group (fails if object is already in another group) void FactionToGroup(object oFactionMember, string sGroupName, int iLeaderPos=GROUP_LEADER_FIRST, int bOverridePrevGroup = FALSE); // add an entire faction to a goup void AddNearestWithTagToGroup(string sGroupName, string sTag, int iMax=20); // adds all in the area w/ tag to a group up to specified max. void EncounterToGroup(string sGroupName, int bWander = 2); // adds all encounter creatures to a group void SpawnCreaturesInGroupAtWP(int iNum, string sTemplate, string sGroupName, string sWayPoint="SPAWN_POINT"); // spawns in creatures and adds them to a group //------------------------------------------------- // Function Definitions //------------------------------------------------- //------------------------------------------------- // Helper functions location GetWPLocation(string sWayPoint) { object oWaypoint = GetWaypointByTag(sWayPoint); return (GetLocation(oWaypoint)); } // Returns number of valid objects in a group int GroupGetNumValidObjects(string sGroupName, int bIsDead = FALSE) { int nCount = 0; int nPossible = GroupGetNumObjects(sGroupName); object oMember; int nHP; int i; for (i=0; i<=nPossible; i++) { oMember = GroupGetObjectIndex(sGroupName, i); if (GetIsObjectValid(oMember) == TRUE) { if (bIsDead == TRUE) { if (GetIsDead(oMember) == FALSE) { nCount = nCount + 1; } } else { nCount = nCount + 1; } } } return (nCount); } // Returns true if at least one group member reference is valid // If bNotDying is TRUE, only check members that are HP>0 int GetIsGroupValid(string sGroupName, int bNotDying = FALSE) { int nPossible = GroupGetNumObjects(sGroupName); object oMember; int i; for (i = 0; i <= nPossible; i++) { oMember = GroupGetObjectIndex(sGroupName, i); if (GetIsObjectValid(oMember) == TRUE) { if (bNotDying == FALSE) { return (TRUE); } else { if (GetIsDead(oMember) == FALSE) { return (TRUE); } } } } return (FALSE); } //Retrieves the group a creature is in //returns the string of the group name, or "" if creature is not in a group // NOTE: may be some problem with creatures who were formerly in a group having the residual variable string GetGroupName(object oMember) { return GetLocalString(oMember,OBJ_GROUP_MY_GROUP); } // Return TRUE, if all remaining members are dominated int GetIsGroupDominated( string sGroupName ) { int nMax = GroupGetNumObjects( sGroupName ); object oGM; int i; for ( i = 0; i <= nMax; i++ ) { oGM = GroupGetObjectIndex( sGroupName, i ); // If member is valid, alive, and not dominated if ( ( GetIsObjectValid(oGM) == TRUE ) && ( GetIsDead(oGM) == FALSE ) && ( GetHasEffectType(oGM, EFFECT_TYPE_DOMINATED) == FALSE ) ) { return ( FALSE ); } } return ( TRUE ); } //--------------------------------------------------------------- // Group Objects object GroupGetObjectIndex(string sGroupName, int iIndex) { string sThisObj = OBJ_GROUP_PREFIX + sGroupName + IntToString(iIndex); return (GetGlobalObject(sThisObj)); } void GroupSetObjectIndex(string sGroupName, int iIndex, object oObject) { string sThisObj = OBJ_GROUP_PREFIX + sGroupName + IntToString(iIndex); SetGlobalObject (sThisObj, oObject); } void GroupDeleteObjectIndex(string sGroupName, int iIndex) { string sThisObj = OBJ_GROUP_PREFIX + sGroupName + IntToString(iIndex); DeleteGlobalObject (sThisObj); } //--------------------------------------------------------------- // Group INTs int GetGroupInt(string sGroupName, string sVarName) { string sThisInt = OBJ_GROUP_PREFIX + sGroupName + sVarName; return (GetGlobalInt(sThisInt)); } void SetGroupInt(string sGroupName, string sVarName, int iValue) { string sThisInt = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalInt(sThisInt, iValue); } void DeleteGroupInt(string sGroupName, string sVarName) { string sThisInt = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalInt(sThisInt, 0); } //--------------------------------------------------------------- // Group FLOATs float GetGroupFloat(string sGroupName, string sVarName) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; return (GetGlobalFloat(sThisVar)); } void SetGroupFloat(string sGroupName, string sVarName, float fValue) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalFloat(sThisVar, fValue); } void DeleteGroupFloat(string sGroupName, string sVarName) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalFloat(sThisVar, 0.0f); } //--------------------------------------------------------------- // Group Strings string GetGroupString(string sGroupName, string sVarName) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; return (GetGlobalString(sThisVar)); } void SetGroupString(string sGroupName, string sVarName, string sValue) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalString(sThisVar, sValue); } //--------------------------------------------------------------- // Group Objects object GetGroupObject(string sGroupName, string sVarName) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; return (GetGlobalObject(sThisVar)); } void SetGroupObject(string sGroupName, string sVarName, object oValue) { string sThisVar = OBJ_GROUP_PREFIX + sGroupName + sVarName; SetGlobalObject(sThisVar, oValue); } // returns current index int GroupGetCurrentIndex(string sGroupName) { return (GetGroupInt(sGroupName, OBJ_GROUP_INDEX)); } void GroupSetCurrentIndex(string sGroupName, int iIndex) { SetGroupInt(sGroupName, OBJ_GROUP_INDEX, iIndex); } // returns number of objects currently stored int GroupGetNumObjects(string sGroupName) { return (GetGroupInt(sGroupName, OBJ_GROUP_NUM)); } void GroupSetNumObjects(string sGroupName, int iNumObjects) { SetGroupInt(sGroupName, OBJ_GROUP_NUM, iNumObjects); } // return current object object GroupGetCurrentObject(string sGroupName) { return (GroupGetObjectIndex(sGroupName, GroupGetCurrentIndex(sGroupName))); } // increments index if possible int GroupIncrementIndex(string sGroupName) { int iCurrentIndex = GroupGetCurrentIndex(sGroupName); int iNumObjects = GroupGetNumObjects(sGroupName); if (iCurrentIndex >= iNumObjects) { return (0); } iCurrentIndex = iCurrentIndex + 1; GroupSetCurrentIndex(sGroupName, iCurrentIndex); PrintString("IncrementIndex: iCurrentIndex = " + IntToString (iCurrentIndex)); return (iCurrentIndex); } // return first valid object in group starting w/ current. // if no more in group, return OBJECT_INVALID object GetFirstValidInGroupFromCurrent(string sGroupName) { object oCurrent = GroupGetCurrentObject(sGroupName); // keep incrementing until we get valid object or reach end of list. while (!GetIsObjectValid(oCurrent)) { if (!GroupIncrementIndex(sGroupName)) return (OBJECT_INVALID); oCurrent = GroupGetCurrentObject(sGroupName); } return oCurrent; } // resets index and returns first object object GetFirstInGroup(string sGroupName) { GroupSetCurrentIndex(sGroupName, 1); return (GetFirstValidInGroupFromCurrent(sGroupName)); //return GroupGetCurrentObject(sGroupName); } // increments index to next valid object and returns current object object GetNextInGroup(string sGroupName) { if (!GroupIncrementIndex(sGroupName)) return (OBJECT_INVALID); return (GetFirstValidInGroupFromCurrent(sGroupName)); } // bOverridePrevGroup - add someone already in another group? int InsertIntoGroup(string sGroupName, object oObject, int bOverridePrevGroup = FALSE) { if (!GetIsObjectValid(oObject)) { PrintString ("ginc_group: InsertIntoGroup - failed - invalid object!"); return 0; } // if not ok to override, then check if already in group. if (!bOverridePrevGroup) { if (GetLocalString(oObject, OBJ_GROUP_MY_GROUP) != ""){ PrintString ("ginc_group: InsertIntoGroup - failed - " + GetName(oObject) + " already in another group"); return 0; } } // track num object? int iNumObjects = GroupGetNumObjects(sGroupName); iNumObjects = iNumObjects + 1; GroupSetNumObjects (sGroupName, iNumObjects); PrintString("InsertIntoGroup - iNumObjects: " + IntToString(iNumObjects)); // assign object GroupSetObjectIndex(sGroupName, iNumObjects, oObject); // let object know what group he is in. SetLocalString(oObject, OBJ_GROUP_MY_GROUP, sGroupName); return (iNumObjects); } //------------------------------------------------- // Functions that do things with Groups //------------------------------------------------- // Determine starting positions for "U6" formation columns: 2,3,4,5,6 indices // 2 3 // 5 4 6 vector GetBMAFormationStartPosition(vector vPosition, int nIndex, float fSpacing, float fFacing) { int nCase = nIndex % 5; // determine starting position if index > 6 if ((nIndex == 0) || (nIndex == 1)) { nCase = 4; } vector vNewPosition = vPosition; switch (nCase) { case 0: // column 1 (left most) vNewPosition = GetChangedPosition(vPosition, fSpacing * 2, fFacing + 180.0); break; case 2: // column 2 (left) fSpacing = sqrt(pow(fSpacing, 2.0) * 2); vNewPosition = GetChangedPosition(vPosition, fSpacing, fFacing + 225.0); break; case 4: // column 3 (center) fSpacing = sqrt(pow(fSpacing, 2.0) * 2) * 2; vNewPosition = GetChangedPosition(vPosition, fSpacing, fFacing + 225.0); break; case 3: // column 4 (right) fSpacing = sqrt(pow(fSpacing, 2.0) * 2); vNewPosition = GetChangedPosition(vPosition, fSpacing, fFacing + 135.0); break; case 1: // column 5 (right most) fSpacing = sqrt(pow(fSpacing, 2.0) * 2) * 2; vNewPosition = GetChangedPosition(vPosition, fSpacing, fFacing + 135.0); break; } return vNewPosition; } // Determine location for "U6" formation: // 1 fSpacing = distance between each row // 2 3 first member of faction should jump to lToJumpTo // 5 4 6 but does that // 7 8 etc. location GetBMALocation(location lToJumpTo, int nIndex, float fSpacing) { PrintString("GetBMALocation(" + IntToString(nIndex)); object oArea = GetAreaFromLocation(lToJumpTo); vector vPosition = GetPositionFromLocation(lToJumpTo); float fFacing = GetFacingFromLocation(lToJumpTo); int nOffset = (nIndex - 2) / 5; // round to floor, determines row offset for indices > 6 if (nIndex >= 2) { vPosition = GetBMAFormationStartPosition(vPosition, nIndex, fSpacing, fFacing); // Pushes the location back per row (indicies 7,8,9, etc.) if (nOffset >= 0) { vPosition = GetChangedPosition(vPosition, IntToFloat(nOffset) * fSpacing * 2, fFacing + 180.0); } } location lNewLocation = Location(oArea, vPosition, fFacing); return lNewLocation; } location GetRectangleLocation(location lDestination, int nMemberIndex, int nColumns, float fSpacing) { object oArea = GetAreaFromLocation(lDestination); vector vPosition = GetPositionFromLocation(lDestination); float fFacing = GetFacingFromLocation(lDestination); int nRow, nCol; nMemberIndex -= 1; //Convert to 0-indexing for the math we're doing below nCol = (nMemberIndex % nColumns); //No divide by 0! if(nColumns == 0) { nColumns = 1; PrintString("Error: Invalid parameter value for nColumns in rectangle formation"); } nRow = nMemberIndex / nColumns; if(nCol != 0) { vPosition = GetChangedPosition(vPosition, fSpacing * nCol, fFacing - 90.f); } if(nRow != 0) { vPosition = GetChangedPosition(vPosition, fSpacing * nRow, fFacing + 180.f); } location lNewLocation = Location(oArea, vPosition, fFacing); return lNewLocation; } location GetHuddleLocation(location lDestination, int iMemberIndex, int iNumObjects, float fRadius=10.0f, int iFaceType=FORMATION_HUDDLE_FACE_IN) { //avoid divide-by-0 errors if(iNumObjects == 0) iNumObjects = 1; iMemberIndex -= 1; //Convert to 0-indexing so first in group goes direction of waypoint. float fIncrement; if(iFaceType == FORMATION_SEMICIRCLE_FACE_OUT || iFaceType == FORMATION_SEMICIRCLE_FACE_IN) { if(iNumObjects == 1) iNumObjects == 2; //hack fix for divide-by-0 fIncrement = 180.f / IntToFloat(iNumObjects - 1); } else { fIncrement = 360.f / IntToFloat(iNumObjects); } float fAngle = fIncrement * iMemberIndex; //for a semicircle, it matters at what angle the semicircle begins. We will use the //base location's facing value (usually a waypoint), and start the semicircle 90 degrees //prior, so the midpoint on the semicircle arc is in the direction the waypoint points. if(iFaceType == FORMATION_SEMICIRCLE_FACE_OUT || iFaceType == FORMATION_SEMICIRCLE_FACE_IN) { fAngle += GetFacingFromLocation(lDestination) - 90.f; } // location lRet = GetHuddleLocation(lDestination, fAngle, fRadius); object oArea = GetAreaFromLocation(lDestination); float fFacing; vector vPos = fRadius * AngleToVector(fAngle); // create vector starting on origin switch (iFaceType) { case FORMATION_HUDDLE_FACE_IN: case FORMATION_SEMICIRCLE_FACE_IN: fFacing = VectorToAngle(-1.0 * vPos); break; case FORMATION_HUDDLE_FACE_OUT: case FORMATION_SEMICIRCLE_FACE_OUT: fFacing = VectorToAngle(vPos); break; case FORMATION_HUDDLE_FACE_FORWARD: fFacing = GetFacingFromLocation(lDestination); break; default: fFacing = VectorToAngle(-1.0 * vPos); break; } vector vCenter = GetPositionFromLocation(lDestination); vPos = vPos + vCenter; // move vector to offset return Location(oArea, vPos, fFacing); } // Get new line location from center of row // 6 4 2 0 1 3 5 location GetLineLocation(location lDestination, int iMemberIndex, float fSpacing) { object oNewArea = GetAreaFromLocation(lDestination); vector vNewPosition = GetPositionFromLocation(lDestination); float fNewFacing = GetFacingFromLocation(lDestination); // if leader then use target destination if (iMemberIndex <= 0) return lDestination; int bOddIndex = (iMemberIndex % 2); if (bOddIndex == TRUE) { // if odd add right vNewPosition = GetChangedPosition(vNewPosition, ((iMemberIndex + 1) / 2) * fSpacing, fNewFacing - 90.0f); } else { // if even add left vNewPosition = GetChangedPosition(vNewPosition, ((iMemberIndex + 1) / 2) * fSpacing, fNewFacing + 90.0f); } return Location(oNewArea, vNewPosition, fNewFacing); } //------------------------------------------------- // Group Base Functions //------------------------------------------------- // removes everything from the group, resets all the group's vars to init values of 0, // and removes local string indicating group from all objects in group void ResetGroup(string sGroupName) { int i; int iNumObjects = GroupGetNumObjects(sGroupName); string sThisObj; object oObject; // set objects to invalid for (i=1; i <= iNumObjects; i++) { oObject = GroupGetObjectIndex(sGroupName, i); if ( GetIsObjectValid(oObject) ) { if ( GetGroupName(oObject) == sGroupName ) { DeleteLocalString( oObject, OBJ_GROUP_MY_GROUP ); } } GroupDeleteObjectIndex(sGroupName, i); } GroupSetNumObjects(sGroupName, 0); GroupSetCurrentIndex(sGroupName, 0); // clear out noise DeleteGroupFloat(sGroupName, OBJ_GROUP_NOISE_START); DeleteGroupFloat(sGroupName, OBJ_GROUP_NOISE_FACING); DeleteGroupFloat(sGroupName, OBJ_GROUP_NOISE_LOCATION); // clear out formation info DeleteGroupFloat(sGroupName, OBJ_GROUP_FORMATION_RADIUS); DeleteGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING); DeleteGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE); DeleteGroupInt(sGroupName, OBJ_GROUP_FORMATION_COLS); } int IsGroupEmpty(string sGroupName) { int iRet = FALSE; if (GroupGetNumObjects(sGroupName) == 0) iRet = TRUE; return (iRet); } //--------------------------------------------------------------- // Group creation //--------------------------------------------------------------- // Make party a group using all standard stuff // This will put all party members in party group even if they are currently in another group. string GetPartyGroup(object oPC) { string sGroupName = PARTY_GROUP_NAME; ResetGroup(sGroupName); //FactionToGroup(oPC, sGroupName, GROUP_LEADER_FIRST, TRUE); GroupAddFaction(sGroupName, oPC, GROUP_LEADER_FIRST, TRUE); GroupSetBMAFormation(sGroupName); return (sGroupName); } // Add creature to group sGroupName void GroupAddMember(string sGroupName, object oMember, int bOverridePrevGroup=FALSE) { InsertIntoGroup(sGroupName, oMember, bOverridePrevGroup); } // Add creatures with factions matching oFactionMember to group sGroupName void GroupAddFaction(string sGroupName, object oFactionMember, int nLeaderPos=GROUP_LEADER_FIRST, int bOverridePrevGroup=FALSE) { object oLeader = GetFactionLeader(oFactionMember); if (!GetIsObjectValid(oLeader)) { oLeader = oFactionMember; } object oMember = GetFirstFactionMember(oFactionMember, FALSE); if (nLeaderPos == GROUP_LEADER_FIRST) // add Leader first { InsertIntoGroup(sGroupName, oLeader, bOverridePrevGroup); } while (GetIsObjectValid(oMember)) { if (oMember != oLeader) // skip Leader { InsertIntoGroup(sGroupName, oMember, bOverridePrevGroup); } oMember = GetNextFactionMember(oFactionMember, FALSE); } if (nLeaderPos == GROUP_LEADER_LAST) // add Leader last { InsertIntoGroup(sGroupName, oLeader, bOverridePrevGroup); } } // Add up to iMax creatures with tag sTag to group sGroupName void GroupAddTag(string sGroupName, string sTag, int iMax=20, int bOverridePrevGroup=FALSE) { int iCount = 0; object oMember = GetObjectByTag(sTag, iCount); while (GetIsObjectValid(oMember) && (iCount < iMax)) { InsertIntoGroup(sGroupName, oMember, bOverridePrevGroup); iCount++; oMember = GetObjectByTag(sTag, iCount); } } // Add up to iMax creatures with tag sTag to group sGroupName void GroupAddNearestTag(string sGroupName, string sTag, object oTarget = OBJECT_SELF, int iMax=20, int bOverridePrevGroup=FALSE) { int iCount = 0; //the + 1 is because GetNearestObjectByTag is 1-indexed, rather than 0-indexed like GetObjectByTag(). -EPF object oMember = GetNearestObjectByTag(sTag, oTarget, iCount + 1); while (GetIsObjectValid(oMember) && (iCount < iMax)) { InsertIntoGroup(sGroupName, oMember, bOverridePrevGroup); iCount++; oMember = GetNearestObjectByTag(sTag, oTarget, iCount + 1); } } // Add encounter spawned creatures to group sGroupName // bWander 0 - no wander // 1 - wander // 2 - don't set (ude default - currently wander) void GroupAddEncounter(string sGroupName, int bWander=2, int bOverridePrevGroup=FALSE) { //SpawnScriptDebugger(); //PrettyDebug("Examining all the creatures in the area"); object oMember = GetFirstObjectInArea(); //int iIsEncounter; //int iIsValid = GetIsObjectValid(oMember); //PrettyDebug("First Obj oin area : " + GetTag(oMember) + " and valid: " + IntToString(iIsValid)); while (GetIsObjectValid(oMember)) { if (GetObjectType(oMember) == OBJECT_TYPE_CREATURE) { //iIsEncounter = GetIsEncounterCreature(oMember); //PrettyDebug(GetName(oMember) + " encounter status is : " + IntToString(iIsEncounter)); if (GetIsEncounterCreature(oMember)) { InsertIntoGroup(sGroupName, oMember, bOverridePrevGroup); // adds } } oMember = GetNextObjectInArea(); } if (bWander != 2) { GroupSetSpawnInCondition(sGroupName, NW_FLAG_AMBIENT_ANIMATIONS, bWander); } } // Note this will only properly place creatures in formation if the group was previously empty. void GroupSpawnAtWaypoint(string sGroupName, string sTemplate, string sWaypoint, int nNum) { object oPC = GetObjectByTag(sWaypoint); location lLoc = GetLocation(oPC); GroupSpawnAtLocation(sGroupName, sTemplate, lLoc, nNum); } // Spawn in iNum sTemplate's into a group using formation & noise at lLocation // Note this will only properly place creatures in formation if the group was previously empty. void GroupSpawnAtLocation(string sGroupName, string sTemplate, location lLocation, int nNum) { object oMember; location lDestination; int nCount; float fFacingNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_FACING); float fLocationNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_LOCATION); int nFormation = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE); int nFormCols = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_COLS); float fFormSpacing = GetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING); for (nCount = 1; nCount <= nNum; nCount++) { switch (nFormation) { case FORMATION_NONE: lDestination = lLocation; break; case FORMATION_HUDDLE_FACE_IN: case FORMATION_HUDDLE_FACE_OUT: case FORMATION_HUDDLE_FACE_FORWARD: lDestination = GetHuddleLocation(lLocation, nCount, nNum, fFormSpacing, nFormation); break; case FORMATION_RECTANGLE: lDestination = GetRectangleLocation(lLocation, nCount, nFormCols, fFormSpacing); break; case FORMATION_BMA: lDestination = GetBMALocation(lLocation, nCount, fFormSpacing); break; case FORMATION_LINE: // 0-based index lDestination = GetLineLocation(lLocation, nCount - 1, fFormSpacing); break; case FORMATION_SEMICIRCLE_FACE_IN: case FORMATION_SEMICIRCLE_FACE_OUT: lDestination = GetHuddleLocation(lLocation, nCount, nNum, fFormSpacing, nFormation); break; default: lDestination = lLocation; break; } lDestination = GetNearbyLocation(lDestination, fLocationNoise, fFacingNoise); oMember = UT_CreateObjectAtLocation(sTemplate, lDestination, "", FALSE); GroupAddMember(sGroupName, oMember); } } // *** old versions // add a new a creature to a group (fails if object is already in another group) int AddToGroup(string sGroupName, object oObject) { //OldFunctionMessage("AddToGroup", "GroupAddMember"); return (InsertIntoGroup(sGroupName, oObject, FALSE)); } // adds all members of a faction to the specified Group void FactionToGroup(object oFactionMember, string sGroupName, int iLeaderPos=GROUP_LEADER_FIRST, int bOverridePrevGroup = FALSE) { OldFunctionMessage("FactionToGroup", "GroupAddFaction"); GroupAddFaction(sGroupName, oFactionMember, iLeaderPos, bOverridePrevGroup); } // add all encounter creatures in area to specified group // bWander 0 - no wander // 1 - wander // 2 - don't set (ude default - currently wander) void EncounterToGroup(string sGroupName, int bWander=2) { OldFunctionMessage("EncounterToGroup", "GroupAddEncounter"); GroupAddEncounter(sGroupName, bWander); } // spawn creatures in - in BMA formation - and add them to a group // if there are creatures already in the group, the new ones will be tacked on to the end and placed // in formation accordingly. void SpawnCreaturesInGroupAtWP(int iNum, string sTemplate, string sGroupName, string sWayPoint="SPAWN_POINT") { int i; object oCreature; location lThisDest; location lDestination = GetWPLocation(sWayPoint); int iIndex; for (i=1; i<=iNum; i++) { iIndex = GroupGetNumObjects(sGroupName)+1; // GroupGetCurrentIndex(sGroupName) + 1; lThisDest = GetBMALocation(lDestination, iIndex, DEFAULT_SPACING); oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lThisDest); //, bUseAppearAnimation, sNewTag); //AddToGroup(sGroupName, oCreature); InsertIntoGroup(sGroupName, oCreature, FALSE); } return; } // adds all in the area w/ tag to a group up to specified max. void AddNearestWithTagToGroup(string sGroupName, string sTag, int iMax=20) { OldFunctionMessage("AddNearestWithTagToGroup", "GroupAddNearestTag"); GroupAddNearestTag(sGroupName, sTag, OBJECT_SELF, iMax); } //-------------------------------------------------- // Formations //-------------------------------------------------- // Use single base destination for group, does NOT ignore noise void GroupSetNoFormation(string sGroupName) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, FORMATION_NONE); } // Creates a standard party group formations: // 1 fSpacing = distance between each row // 2 3 // 5 4 6 // 7 8 etc. void GroupSetBMAFormation(string sGroupName, float fSpacing=1.8f) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, FORMATION_BMA); SetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING, fSpacing); // to be implemented } // creates a circle, fRadius out from the waypoint. First in group will go in direction of waypoints arrow. // int iFormation - Formation to use // float fRadius - radius for huddles void GroupSetCircleFormation(string sGroupName, int iFacing=FORMATION_HUDDLE_FACE_IN , float fRadius=5.0f) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, iFacing); SetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING, fRadius); } // Just like GroupSetCircleFormation, but we only cover the first half of the circle. void GroupSetSemicircleFormation(string sGroupName, int nFacing = FORMATION_SEMICIRCLE_FACE_OUT, float fRadius = 5.f) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, nFacing); SetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING, fRadius); } // Create standard single row formation, leader in middle // 6 4 2 0 1 3 5 void GroupSetLineFormation(string sGroupName, float fSpacing=DEFAULT_SPACING) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, FORMATION_LINE); SetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING, fSpacing); } // creates a rectangle with creatures facing direction of waypoint. Waypoint indicates top left most // corner of the rectangle. // float fSpacing - spacing in units between creatures. There are 10 units in a single tile square // int nColumns - number of columns to form. void GroupSetRectangleFormation(string sGroupName, float fSpacing=1.8f, int nColumns=2) { SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE, FORMATION_RECTANGLE); SetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING, fSpacing); SetGroupInt(sGroupName, OBJ_GROUP_FORMATION_COLS, nColumns); } // Sets the noise to be used with formations to make them less synchronized. // fStartNoise - delay in start time for creatures to move // fFacingNoise - max degrees to turn from facing // fLocationNoise - max x and y units to deviate from location void GroupSetNoise(string sGroupName, float fStartNoise=1.0f, float fFacingNoise=10.0f, float fLocationNoise=1.0f) { SetGroupFloat(sGroupName, OBJ_GROUP_NOISE_START, fStartNoise); SetGroupFloat(sGroupName, OBJ_GROUP_NOISE_FACING, fFacingNoise); SetGroupFloat(sGroupName, OBJ_GROUP_NOISE_LOCATION, fLocationNoise); } // sets up variables so everyone in group runs a script on death which will // start a conversation when all are dead. // do not add people to group after calling this as they will not have their death script assigned. void GroupOnDeathBeginConversation(string sGroupName, string sTalkerTag, string sConversation) { // set groups death script GroupSetLocalString (sGroupName, "DeathScript", "gg_death_talk"); // set vars for later use SetGroupString(sGroupName, "TalkerTag", sTalkerTag); SetGroupString(sGroupName, "Conversation", sConversation); // reset num killed (in case group name was used before) SetGroupInt(sGroupName, "NumKilled", 0); } void GroupOnDeathSetLocalInt( string sGroupName, object oTargetObject, string sVariableName, int nNewValue ) { // set groups death script GroupSetLocalString ( sGroupName, "DeathScript", "gg_death_l_var" ); // set vars for later use SetGroupObject( sGroupName, "TargetObject", oTargetObject ); SetGroupString( sGroupName, "VarName", sVariableName ); SetGroupInt( sGroupName, "VarValue", nNewValue ); SetGroupInt( sGroupName, "VarType", TYPE_INT ); // reset num killed (in case group name was used before) SetGroupInt( sGroupName, "NumKilled", 0 ); } void GroupOnDeathSetLocalFloat( string sGroupName, object oTargetObject, string sVariableName, float fNewValue ) { // set groups death script GroupSetLocalString (sGroupName, "DeathScript", "gg_death_l_var" ); // set vars for later use SetGroupObject( sGroupName, "TargetObject", oTargetObject ); SetGroupString( sGroupName, "VarName", sVariableName ); SetGroupFloat( sGroupName, "VarValue", fNewValue ); SetGroupInt( sGroupName, "VarType", TYPE_FLOAT ); // reset num killed (in case group name was used before) SetGroupInt(sGroupName, "NumKilled", 0); } void GroupOnDeathSetLocalString( string sGroupName, object oTargetObject, string sVariableName, string sNewValue ) { // set groups death script GroupSetLocalString (sGroupName, "DeathScript", "gg_death_l_var" ); // set vars for later use SetGroupObject( sGroupName, "TargetObject", oTargetObject ); SetGroupString( sGroupName, "VarName", sVariableName ); SetGroupString( sGroupName, "VarValue", sNewValue ); SetGroupInt( sGroupName, "VarType", TYPE_STRING ); // reset num killed (in case group name was used before) SetGroupInt(sGroupName, "NumKilled", 0); } // Works with gg_death_journal, where AddJournalQuestEntry will be called using the below params. void GroupOnDeathSetJournalEntry(string sGroup, string sQuestTag, int nEntry, int bAllowOverride = FALSE) { GroupSetLocalString(sGroup, "DeathScript", "gg_death_journal"); SetGroupString(sGroup, "sQuestTag", sQuestTag); SetGroupInt(sGroup, "nEntry", nEntry); SetGroupInt(sGroup, "bOverride", bAllowOverride); } // Works with gg_death_custom_script, which will call sScriptName on the Module void GroupOnDeathExecuteCustomScript(string sGroupName, string sScriptName) { // set groups death script GroupSetLocalString ( sGroupName, "DeathScript", "gg_death_custom_script" ); // set vars for later use SetGroupString( sGroupName, "CustomScript", sScriptName ); // reset num killed (in case group name was used before) SetGroupInt( sGroupName, "NumKilled", 0 ); } //---------------------------------------------------- // Group Commands // void GroupForceMoveToLocation(string sGroupName, location lDestination, int bRun=FALSE, float fTimeout=30.0f) { int nNumMembers = GroupGetNumObjects(sGroupName); object oMember = GetFirstInGroup(sGroupName); location lNewDest; float fFacingNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_FACING); float fLocationNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_LOCATION); int nFormation = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE); int nFormCols = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_COLS); float fFormSpacing = GetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING); int nCount; for (nCount = 1; nCount <= nNumMembers; nCount++) { switch (nFormation) { case FORMATION_NONE: lNewDest = lDestination; break; case FORMATION_HUDDLE_FACE_IN: case FORMATION_HUDDLE_FACE_OUT: case FORMATION_HUDDLE_FACE_FORWARD: lDestination = GetHuddleLocation(lDestination, nCount, nNumMembers, fFormSpacing, nFormation); break; case FORMATION_RECTANGLE: lNewDest = GetRectangleLocation(lDestination, nCount, nFormCols, fFormSpacing); break; case FORMATION_BMA: lNewDest = GetBMALocation(lDestination, nCount, fFormSpacing); break; case FORMATION_LINE: // 0-based index lNewDest = GetLineLocation(lDestination, nCount - 1, fFormSpacing); break; case FORMATION_SEMICIRCLE_FACE_IN: case FORMATION_SEMICIRCLE_FACE_OUT: lDestination = GetHuddleLocation(lDestination, nCount, nNumMembers, fFormSpacing, nFormation); break; default: lNewDest = lDestination; break; } lNewDest = GetNearbyLocation(lNewDest, fLocationNoise, fFacingNoise); PrettyMessage("ginc_group: force moving " + GetName(oMember)); AssignCommand(oMember, ActionForceMoveToLocation(lNewDest, bRun, fTimeout)); oMember = GetNextInGroup(sGroupName); } } // locomote a group to a specified waypoint (formation and noise should be set first) // string sGroupName - name of group to move (created using AddToGroup()) // string sWayPoint - Tag of the Base waypoint for the formation // int iMoveType - specifies type of locomotion - MOVE_WALK, MOVE_JUMP, etc. void GroupMoveToWP(string sGroupName, string sWayPoint, int iMoveType=MOVE_WALK) { location lDestination = GetWPLocation(sWayPoint); GroupMoveToFormationLocation(sGroupName, lDestination, iMoveType); } void GroupMoveToObject(string sGroupName, object oTarget, int iMoveType=MOVE_WALK) { location lDestination = GetLocation(oTarget); GroupMoveToFormationLocation(sGroupName, lDestination, iMoveType); } void GroupFleeToExit(string sGroupName, string sWaypoint, int iMoveType=MOVE_WALK) { GroupMoveToWP(sGroupName, sWaypoint, iMoveType); object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, ActionDoCommand(DestroyObject(oMember))); oMember = GetNextInGroup(sGroupName); } } // wrapper for MOVE_JUMP_INSTANT - clear actions and jump to location void GroupJumpToWP(string sGroupName, string sWaypoint) { GroupMoveToWP(sGroupName, sWaypoint, MOVE_JUMP_INSTANT); //location lDestination = GetWPLocation(sWaypoint); //GroupMoveToFormationLocation(sGroupName, lDestination, MOVE_JUMP_INSTANT); } // locomote a group to a specified location (formation and noise should be set first) // string sGroupName - name of group to move (created using AddToGroup()) // location lDestination - Base location for the formation // int iMoveType - specifies type of locomotion - MOVE_WALK, MOVE_JUMP, etc. void GroupMoveToFormationLocation(string sGroupName, location lDestination, int iMoveType=MOVE_WALK) { object oMember = GetFirstInGroup(sGroupName); location lThisDest; float fFacing; int iMemberIndex; // get stored noise float fStartNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_START); float fFacingNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_FACING); float fLocationNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_LOCATION); // get formation vars int iFormation = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_TYPE); int iNumObjects = GroupGetNumObjects(sGroupName); int iCols = GetGroupInt(sGroupName, OBJ_GROUP_FORMATION_COLS); float fSpacing = GetGroupFloat(sGroupName, OBJ_GROUP_FORMATION_SPACING); while (GetIsObjectValid(oMember)) { iMemberIndex = GroupGetCurrentIndex(sGroupName); //lThisDest = GetFormationLocationByIndex(lDestination, sGroupName, iFormation, fRadius); //lThisDest = GetFormationLocationByIndex(lDestination, sGroupName); switch (iFormation) { case FORMATION_NONE: lThisDest = lDestination; break; case FORMATION_HUDDLE_FACE_IN: // do a huddle case FORMATION_HUDDLE_FACE_OUT: // do a backward huddle case FORMATION_HUDDLE_FACE_FORWARD: // forward moving circle lThisDest = GetHuddleLocation(lDestination, iMemberIndex, iNumObjects, fSpacing, iFormation); break; case FORMATION_RECTANGLE: lThisDest = GetRectangleLocation(lDestination, iMemberIndex, iCols, fSpacing); break; case FORMATION_BMA: lThisDest = GetBMALocation(lDestination, iMemberIndex, fSpacing); break; case FORMATION_LINE: // 0-based index what val does iMemberIndex start at? lThisDest = GetLineLocation(lDestination, iMemberIndex - 1, fSpacing); break; case FORMATION_SEMICIRCLE_FACE_IN: case FORMATION_SEMICIRCLE_FACE_OUT: lThisDest = GetHuddleLocation(lDestination, iMemberIndex, iNumObjects, fSpacing, iFormation); break; default: lThisDest = GetBMALocation(lDestination, iMemberIndex, DEFAULT_SPACING); break; } PrintString("ginc_group: GroupMoveToWP() object " + GetName(oMember) + " type " + IntToString(iMoveType)); lThisDest = GetNearbyLocation(lThisDest, fLocationNoise); switch (iMoveType) { case MOVE_WALK: AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); AssignCommand(oMember, ActionMoveToLocation(lThisDest)); break; case MOVE_RUN: AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); AssignCommand(oMember, ActionMoveToLocation(lThisDest, TRUE)); break; case MOVE_JUMP: AssignCommand(oMember, ActionJumpToLocation(lThisDest)); break; case MOVE_JUMP_INSTANT: AssignCommand(oMember, ClearAllActions()); AssignCommand(oMember, JumpToLocation(lThisDest)); break; case MOVE_FORCE_WALK: AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); AssignCommand(oMember, ActionForceMoveToLocation(lThisDest)); case MOVE_FORCE_RUN: AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); AssignCommand(oMember, ActionForceMoveToLocation(lThisDest, TRUE)); default: PrintString("ginc_group: invalid iMoveType case"); AssignCommand(oMember, ActionMoveToLocation(lThisDest)); break; } // face the same way as the location destination + some noise fFacing = GetNormalizedDirection(GetFacingFromLocation(lThisDest) + RandomDelta(fFacingNoise)); AssignCommand(oMember, ActionDoCommand(SetFacing(fFacing))); AssignCommand(oMember, ActionWait(0.5f)); // wait for facing oMember = GetNextInGroup(sGroupName); } } // have group attak target // string sGroupName - name of group // object oTarget - target to attack void GroupAttack(string sGroupName, object oTarget) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { StandardAttack(oMember, oTarget); oMember = GetNextInGroup(sGroupName); } } // all in group clear their actions // string sGroupName - name of group // int nClearCombatState void GroupClearAllActions(string sGroupName, int nClearCombatState = FALSE) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { AssignCommand(oMember, ClearAllActions(nClearCombatState)); //PrintString (GetName(oMember) + " - Actions Cleared"); oMember = GetNextInGroup(sGroupName); } } // makes a group play an animation void GroupPlayAnimation(string sGroupName, int nAnimation, float fStartNoise=1.0f, float fSpeedBase=1.0f, float fSpeedRange=1.0f, float fDurationSectondsBase=0.0f, float fDurationSectondsRange=0.0f) { object oMember = GetFirstInGroup(sGroupName); float fSpeed; float fDurationSectonds; while (GetIsObjectValid(oMember)) { if (fStartNoise > EPSILON) AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); fSpeed = fSpeedBase; if (fSpeedRange > EPSILON) fSpeed = fSpeed + RandomFloat(fStartNoise); fDurationSectonds = fDurationSectondsBase; if (fDurationSectondsRange > EPSILON) fDurationSectonds = fDurationSectonds + RandomFloat(fDurationSectondsRange); AssignCommand(oMember, ActionPlayAnimation(nAnimation, fSpeed, fDurationSectonds)); oMember = GetNextInGroup(sGroupName); } } // all in group wait void GroupActionWait(string sGroupName, float fSeconds=0.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { AssignCommand(oMember, ActionWait(fSeconds)); oMember = GetNextInGroup(sGroupName); } } // causes all in group to change facing // uses start noise void GroupActionOrientToTag(string sGroupName, string sTag, int iOrientation=ORIENT_FACE_TARGET, int bIgnoreWait=FALSE) { object oMember = GetFirstInGroup(sGroupName); float fStartNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_START); while (GetIsObjectValid(oMember)) { if (bIgnoreWait == FALSE) AssignCommand(oMember, ActionWait(RandomFloat(fStartNoise))); AssignCommand(oMember, ActionOrientToTag(sTag, iOrientation)); oMember = GetNextInGroup(sGroupName); } } void GroupResurrect(string sGroupName, int bIgnoreWait=FALSE) { object oMember = GetFirstInGroup(sGroupName); float fStartNoise = GetGroupFloat(sGroupName, OBJ_GROUP_NOISE_START); float fDelay = 0.0f; while (GetIsObjectValid(oMember) == TRUE) { if (bIgnoreWait == FALSE) { fDelay = RandomFloat(fStartNoise); } AssignCommand(oMember, DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oMember))); oMember = GetNextInGroup(sGroupName); } } // sets a string on all in the group void GroupSetLocalString (string sGroupName, string sVarName, string sValue) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { PrintString("ginc_group: GroupSetLocalString() group " + sGroupName + " object " + GetName(oMember) + " var " + sVarName + " = " + sValue); SetLocalString(oMember, sVarName, sValue); oMember = GetNextInGroup(sGroupName); } } // sets an object on all in the group void GroupSetLocalObject (string sGroupName, string sVarName, object oValue) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { //PrintString("ginc_group: GroupSetLocalObject() group " + sGroupName + " object " + GetName(oMember) + " var " + sVarName + " = " + GetName(oValue)); SetLocalObject(oMember, sVarName, oValue); oMember = GetNextInGroup(sGroupName); } } // sets an object on all in the group void GroupSetLocalInt (string sGroupName, string sVarName, int iValue) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { //PrintString("ginc_group: GroupSetLocalObject() group " + sGroupName + " object " + GetName(oMember) + " var " + sVarName + " = " + GetName(oValue)); SetLocalInt(oMember, sVarName, iValue); oMember = GetNextInGroup(sGroupName); } } // sets an object on all in the group void GroupSetLocalFloat (string sGroupName, string sVarName, float fValue) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { //PrintString("ginc_group: GroupSetLocalFloat() group " + sGroupName + " object " + GetName(oMember) + " var " + sVarName + " = " + GetName(oValue)); SetLocalFloat(oMember, sVarName, fValue); oMember = GetNextInGroup(sGroupName); } } // sets specified spawn in condition for all in group void GroupSetSpawnInCondition(string sGroupName, int nCondition, int bValid = TRUE) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { SetSpawnInCondition(nCondition, bValid); oMember = GetNextInGroup(sGroupName); } } // Turns ambient animations flag on/off for all in group void GroupWander(string sGroupName, int bValid = TRUE) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, bValid); if (bValid) AssignCommand(oMember, PlayMobileAmbientAnimations()); else AssignCommand(oMember, ClearAllActions()); oMember = GetNextInGroup(sGroupName); } } // forces all in group to go to destination and then destroy self. void GroupActionForceExit(string sGroupName, string sWPTag = "WP_EXIT", int bRun=FALSE) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { AssignCommand(oMember, ActionForceExit(sWPTag, bRun)); oMember = GetNextInGroup(sGroupName); } } // Changes everyone in group to join faction of given creature // Note on use: mod should contain an isolated area with a faction pig for // each faction in use w/ tag same as faction name. // (faction pigs have no scripts and thus can be placed peacefully together) void GroupChangeFaction(string sGroupName, string sTargetFactionMember) { object oTargetFactionMember = GetObjectByTag(sTargetFactionMember); object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { ChangeFaction(oMember, oTargetFactionMember); //PrintString ("Changed to same faction as " + GetName(oTarget)); oMember = GetNextInGroup(sGroupName); } } // Changes everyone in group to join one of the standard factions // STANDARD_FACTION_COMMONER; // STANDARD_FACTION_DEFENDER; // STANDARD_FACTION_HOSTILE; // STANDARD_FACTION_MERCHANT; void GroupChangeToStandardFaction(string sGroupName, int iFaction) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { ChangeToStandardFaction(oMember, iFaction); //PrintString ("Changed to standard faction"); oMember = GetNextInGroup(sGroupName); } } // does action move to object for all in group void GroupActionMoveToObject(string sGroupName, object oTarget, int bRun = FALSE, float fRange = 1.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { AssignCommand(oMember, ActionMoveToObject( oTarget, bRun, fRange)); oMember = GetNextInGroup(sGroupName); } } // have group attak targets in another group // string sAttackerGroupName - name of attacking group // string sAttackedGroupName - name of attacked group void GroupAttackGroup(string sAttackerGroupName, string sAttackedGroupName) { object oMember = GetFirstInGroup(sAttackerGroupName); object oTarget = GetFirstInGroup(sAttackedGroupName); while (GetIsObjectValid(oMember)) { StandardAttack(oMember, oTarget); oMember = GetNextInGroup(sAttackerGroupName); oTarget = GetNextInGroup(sAttackedGroupName); if (oTarget == OBJECT_INVALID) oTarget = GetFirstInGroup(sAttackedGroupName); } } // assign SetFacingPoint() to each member in group, ignore noise void GroupSetFacingPoint(string sGroupName, vector vPoint) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, SetFacingPoint(vPoint)); oMember = GetNextInGroup(sGroupName); } } // Destroys all objects in the group void DestroyObjectsInGroup(string sGroupName, float fDelay = 0.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { PrintString("ginc_group: DestroyObjectsInGroup() destroying " + GetName(oMember) + " of group " + sGroupName); DestroyObject(oMember, fDelay); oMember = GetNextInGroup(sGroupName); } } void GroupSetImmortal(string sGroupName, int bImmortal) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { SetImmortal(oMember, bImmortal); oMember = GetNextInGroup(sGroupName); } } void GroupSetPlotFlag(string sGroupName, int bPlotFlag) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { SetPlotFlag(oMember, bPlotFlag); oMember = GetNextInGroup(sGroupName); } } // use GroupClearAllActions() to cancel follow. // this will cause group to follow leader around for a while - eventually an event will // clear their actions and they will go do their own thing. void GroupActionForceFollowObject(string sGroupName, object oMaster, float fFollowDistance = 5.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, ActionForceFollowObject(oMaster, fFollowDistance)); PrintString(GetName(oMember) + " following " + GetName(oMaster)); oMember = GetNextInGroup(sGroupName); } } // Cuases group to follow master // the prospective followers must use heartbeat script "gb_follow_hb" for the effect to persist. void GroupStartFollowLeader(string sGroupName, object oMaster, float fFollowDistance = 5.0f) { GroupSetLocalObject (sGroupName, "Leader", oMaster); GroupSetLocalFloat (sGroupName, "FollowDistance", fFollowDistance); GroupActionForceFollowObject(sGroupName, oMaster, fFollowDistance); } // cuases group to stop following master void GroupStopFollowLeader(string sGroupName) { GroupSetLocalObject (sGroupName, "Leader", OBJECT_INVALID); GroupClearAllActions(sGroupName); } // figure out for selves what to do. void GroupDetermineCombatRound(string sGroupName) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, DetermineCombatRound()); oMember = GetNextInGroup(sGroupName); } } // puts creatures in hostile faction and has them DetermineCombatRound() void GroupGoHostile(string sGroupName) { GroupChangeToStandardFaction(sGroupName, STANDARD_FACTION_HOSTILE); GroupDetermineCombatRound(sGroupName); } // note: testing on 9/14/05 indicates SurrenderToEnemies() is unreliable. void GroupSurrenderToEnemies(string sGroupName) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, SurrenderToEnemies()); oMember = GetNextInGroup(sGroupName); } } void GroupActionMoveAwayFromObject(string sGroupName, object oFleeFrom, int bRun = FALSE, float fMoveAwayRange = 40.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, ActionMoveAwayFromObject(oFleeFrom, bRun, fMoveAwayRange)); oMember = GetNextInGroup(sGroupName); } } // everyone in group casts same fake spell void GroupActionCastFakeSpellAtObject(string sGroupName, int nSpell, object oTarget, int nProjectilePathType = PROJECTILE_PATH_TYPE_DEFAULT) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { AssignCommand(oMember, ActionCastFakeSpellAtObject(nSpell, oTarget, nProjectilePathType)); oMember = GetNextInGroup(sGroupName); } } void GroupApplyEffectToObject(string sGroupName, int nDurationType, effect eEffect, float fDuration = 0.0f) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { ApplyEffectToObject(nDurationType, eEffect, oMember, fDuration); oMember = GetNextInGroup(sGroupName); } } void GroupRemoveEffectOfType(string sGroupName, int nEffectType) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { RemoveEffectOfType(oMember, nEffectType); oMember = GetNextInGroup(sGroupName); } } void GroupSignalEvent(string sGroupName, event eEvent) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember) == TRUE) { SignalEvent(oMember, eEvent); oMember = GetNextInGroup(sGroupName); } } void GroupSetScriptHidden(string sGroupName, int bHidden) { object oMember = GetFirstInGroup(sGroupName); while (GetIsObjectValid(oMember)) { SetScriptHidden(oMember, bHidden); oMember = GetNextInGroup(sGroupName); } } int IncGroupNumKilled( string sGroupName ) { int nNumKilled = GetGroupInt( sGroupName, GROUP_VAR_NUM_KILLED ) + 1; SetGroupInt( sGroupName, GROUP_VAR_NUM_KILLED, nNumKilled ); return ( nNumKilled ); } int GetGroupNumKiled( string sGroupName ) { int nNumKilled = GetGroupInt( sGroupName, GROUP_VAR_NUM_KILLED ); return ( nNumKilled ); } // Sets destroyable status of members in sGroupName // - bDestroyable: If FALSE, members do not fade out and stick around as corpses. // - bRaisable: If TRUE, members can be raised via resurrection. // - bSelectableWhenDead: If TRUE, members are selectable after death. void GroupSetIsDestroyable( string sGroupName, int bDestroyable, int bRaisable=TRUE, int bSelectableWhenDead=FALSE ) { object oGM = GetFirstInGroup( sGroupName ); while ( GetIsObjectValid( oGM ) == TRUE ) { AssignCommand( oGM, SetIsDestroyable( bDestroyable, bRaisable, bSelectableWhenDead ) ); oGM = GetNextInGroup( sGroupName ); } } // ginc_gui.nss /* GUI/Screen campaign include */ // BMA-OEI 4/06/06 // BMA-OEI 8/22/06 -- Renamed to ginc_gui, moved GUI_DEATH* to ginc_death // BMA-OEI 9/28/06 -- Added GUI_PARTY_SELECT_CANCEL const string GUI_LOAD_GAME = "SCREEN_LOADGAME"; const string GUI_PARTY_SELECT = "SCREEN_PARTYSELECT"; const string GUI_PARTY_SELECT_CANCEL = "REMOVE_PARTY"; const string GUI_PARTY_SELECT_CLOSE = "CloseButton"; // Displays Load Game screen to oPC void ShowLoadGame( object oPC ); // Displays Party Selection screen to oPC // - bModal: T/F, Display window modally // - sAcceptCallback: Callback script executed when party is accepted // - bCloseButton: T/F, Enable close button void ShowPartySelect( object oPC, int bModal=TRUE, string sAcceptCallback="", int bCloseButton=FALSE ); // Hides Party Selection screen for oPC void HidePartySelect( object oPC ); // Displays Load Game screen to oPC void ShowLoadGame( object oPC ) { DisplayGuiScreen( oPC, GUI_LOAD_GAME, FALSE ); } // Displays Party Selection screen to oPC // - bModal: T/F, Display window modally // - sAcceptCallback: Callback script executed when party is accepted // - bCloseButton: T/F, Enable close button void ShowPartySelect( object oPC, int bModal=TRUE, string sAcceptCallback="", int bCloseButton=FALSE ) { SetGUIObjectDisabled( oPC, GUI_PARTY_SELECT, GUI_PARTY_SELECT_CANCEL, !bCloseButton ); SetGUIObjectDisabled( oPC, GUI_PARTY_SELECT, GUI_PARTY_SELECT_CLOSE, !bCloseButton ); SetLocalGUIVariable( oPC, GUI_PARTY_SELECT, 0, sAcceptCallback ); DisplayGuiScreen( oPC, GUI_PARTY_SELECT, TRUE ); } // Hides Party Selection screen for oPC void HidePartySelect( object oPC ) { CloseGUIScreen( oPC, GUI_PARTY_SELECT ); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ginc_henchman //:: //:: Common functions and definitions used in: //:: ga_henchman_add //:: ga_henchman_remove //:: ga_henchman_replace //:: ga_henchman_setmax //:: gc_henchman_getmax //:: //:: As well as some functions that may be helpful elsewhere //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 1/28/06 // ChazM 1/30/06 - added ginc_event_handlers, modified HenchmanAdd(), HenchmanRemove() // ChazM 3/8/06 - added DestroyHenchman(),DestroyAllHenchmen(), DestroyAllHenchmenInParty() //void main() {} #include "ginc_event_handlers" //===============================================================================General Purpose Section: //Prototypes: int GetNumHenchmen(object oMaster); //returns the number of henchman oMaster currently has int GetIsHenchman(object oMaster, object oHench); //checks to see if oHench is a henchman of oMaster //Function definitions //Returns the number of henchmen that oMaster has. int GetNumHenchmen(object oMaster) { int nLoop, nCount=0; for (nLoop=1; nLoop<=GetMaxHenchmen()+3; nLoop++) { if (GetIsObjectValid(GetHenchman(oMaster, nLoop))) nCount+=1; } return nCount; } /* int GetNumHenchmen(object oMaster=OBJECT_SELF) { int i = 1; object oHenchman = GetHenchman(oMaster, i); while (GetIsObjectValid(oHenchman)) { i++; //PrettyDebug ("GetNumHenchmen() - found: " + GetName(oHenchman)); oHenchman = GetHenchman(oMaster, i); } i = i-1; //PrettyDebug ("GetNumHenchmen() - Total found = " + IntToString(i)); return (i); } */ //Checks to see if a creature is a henchman of another. // parameters: checks to see if oHench is a henchman of oMaster // returns 1 if oHench is a henchman, 0 if not. int GetIsHenchman(object oMaster, object oHench) { int nMaxHench = GetMaxHenchmen()+6; //just in case a few have been forced int i; for (i=1;i=nMax) { SetMaxHenchmen(nCur+1); AddHenchman(oMaster,oHench); SetMaxHenchmen(nMax); } else AddHenchman(oMaster,oHench); } else if (nCur=1; i--) { oHenchman = GetHenchman(oMaster, i); //PrettyDebug ("Removing " + GetName(oHenchman)); //RemoveHenchman(oMaster, oHenchman); //SetPlotFlag(oHenchman, FALSE); DelayCommand(0.5f, DestroyHenchman(oHenchman)); // delay destructions so we have time to iterate through party properly } } // Destroy every henchman in the entire party void DestroyAllHenchmenInParty(object oPartyMember) { object oFM = GetFirstFactionMember(oPartyMember, FALSE); while(GetIsObjectValid(oFM)) { //PrettyDebug ("Examining " + GetName(oFM) + " for henchmen."); DestroyAllHenchmen(oFM); oFM = GetNextFactionMember(oPartyMember, FALSE); } } // ginc_ipspeaker /* Various functions for IPoint Speaker pending conversations Used in gp_ipspeaker_hb, gg_death_talk */ // BMA-OEI 1/23/06 // BMA-OEI 2/8/06 - Added bDeleteSelf, bFadeOut // DBR 2/09/06 - Temporarily removed return on not finding a speaker tag to prevent drop-outs // BMA-OEI 2/14/06 - removed fade out // BMA-OEI 2/15/06 - set plot false on delete self // BMA-OEI 3/6/06 - added IPS_RESREF, updated prototypes, revised comments, added CombatCutsceneSetup // BMA-OEI 3/7/06 - modified CombatCutsceneCleanUp to use IPoint Cleaner // BMA-OEI 3/8/06 - minimum distance for JumpPartyToSpeaker() // BMA-OEI 3/14/06 - added CreateIPSpeaker() // BMA-OEI 4/13/06 - added fDelay param to CreateIPSpeaker() and ResetIPSpeaker() #include "ginc_cutscene" #include "ginc_debug" // ***** CONSTANTS ***** const string IPS_RESREF = "plc_ipspeaker"; const string IPS_SPEAKER_TAG = "__sSpeakerTag"; const string IPS_CONVERSATION = "__sConversation"; const string IPS_PENDING = "__bPendingConv"; const string IPS_DELETE_SELF = "__bDeleteSelf"; const string IPS_LOCK_VAR = "__bIPSLocked"; // ***** PROTOTYPES ***** // Create and setup IPSpeaker for pending conversation // - sSpeakerTag: Non-hostile owner to assign conversation // - sConversation: Conversation to use // - lLoc: Location to create IPSpeaker conversation manager // - fDelay: Delay before first conversation attempt object CreateIPSpeaker(string sSpeakerTag, string sConversation, location lLoc, float fDelay=0.0f); // Setup IPoint Speaker for pending conversation // - oIPSpeaker: IPSpeaker object ID // - sSpeakerTag: Non-hostile owner to assign conversation // - sConversation: Conversation to use // - bPending: Flags that a conversation is pending for conversation attempts // - bDeleteSelf: Flag to Delete IPSpeaker after conversation is fired // - fDelay: Delay before first conversation attempt void ResetIPSpeaker(object oIPSpeaker, string sSpeakerTag, string sConversation, int bPending=TRUE, int bDeleteSelf=FALSE, float fDelay=0.0f); // Check if AttemptIPSConversation() has been recently executed int GetIsIPSLocked(); // Set IPS_LOCK_VAR local var to avoid synchronous AttemptIPSConversation() execution void SetIPSLocked(int bLocked); // Attempt pending conversation if conditions are met void AttemptIPSConversation(object oIPSpeaker=OBJECT_SELF); // Check if a pending conversation is ready to play int GetIsIPSConversationPending(object oIPSpeaker=OBJECT_SELF); // Set IPS_PENDING local var to flag a pending conversation as ready to play void SetIPSConversationPending(object oIPSpeaker=OBJECT_SELF, int bPending=TRUE); // Check if oObject is safe to conversate (in area, not in conversation) int GetIsIPSConversible(object oObject, object oIPSpeaker=OBJECT_SELF); // ***** DEFINITIONS ***** // Create and setup IPSpeaker for pending conversation object CreateIPSpeaker(string sSpeakerTag, string sConversation, location lLoc, float fDelay=0.0f) { //PrettyDebug("CreateIPSpeaker: " + sSpeakerTag + sConversation); object oIPS = CreateObject(OBJECT_TYPE_PLACEABLE, IPS_RESREF, lLoc); if ( GetIsObjectValid(oIPS) == FALSE ) PrettyError("CreateIPSpeaker: oIPS is not valid!"); AssignCommand(oIPS, ResetIPSpeaker(oIPS, sSpeakerTag, sConversation, TRUE, TRUE, fDelay)); return ( oIPS ); } // Setup IPoint Speaker for pending conversation void ResetIPSpeaker(object oIPSpeaker, string sSpeakerTag, string sConversation, int bPending=TRUE, int bDeleteSelf=FALSE, float fDelay=0.0f) { //PrettyMessage("ResetIPSpeaker: !"); SetLocalString(oIPSpeaker, IPS_SPEAKER_TAG, sSpeakerTag); SetLocalString(oIPSpeaker, IPS_CONVERSATION, sConversation); SetLocalInt(oIPSpeaker, IPS_PENDING, bPending); SetLocalInt(oIPSpeaker, IPS_DELETE_SELF, bDeleteSelf); DelayCommand(fDelay, AttemptIPSConversation()); DelayCommand(3.0f, AttemptIPSConversation()); } // Heartbeat handler for gp_ipspeaker_hb void IPSpeakerHeartbeat() { AttemptIPSConversation(); DelayCommand(1.5f, AttemptIPSConversation()); DelayCommand(3.0f, AttemptIPSConversation()); } // Check if AttemptIPSConversation() has been recently executed int GetIsIPSLocked() { return GetGlobalInt(IPS_LOCK_VAR); } // Set IPS_LOCK_VAR local var to avoid synchronous AttemptIPSConversation() execution void SetIPSLocked(int bLocked) { SetGlobalInt(IPS_LOCK_VAR, bLocked); } // Attempt pending conversation if conditions are met void AttemptIPSConversation(object oIPSpeaker=OBJECT_SELF) { //PrettyMessage("AttemptIPSConversation: checking..."); if (GetIsIPSLocked() == 1) { //PrettyError("IPS is locked! Unlocking in 0.5fs"); DelayCommand(0.5f, SetIPSLocked(0)); return; } //PrettyMessage(GetLocalString(oIPSpeaker, IPS_SPEAKER_TAG)); //PrettyMessage(GetLocalString(oIPSpeaker, IPS_CONVERSATION)); //PrettyMessage(IntToString(GetLocalInt(oIPSpeaker, IPS_PENDING))); //PrettyMessage(IntToString(GetLocalInt(oIPSpeaker, IPS_DELETE_SELF))); // Lock to avoid near future execution SetIPSLocked(1); // If a conversation is pending if (GetIsIPSConversationPending() == TRUE) { //PrettyDebug( "AttemptIPSConversation: IPS conversation is pending..." ); object oPC = GetFactionLeader(GetFirstPC()); string sSpeakerTag = GetLocalString(oIPSpeaker, IPS_SPEAKER_TAG); if (sSpeakerTag == "") { PrettyError("ERROR: gp_ipspeaker_hb: sSpeakerTag is not set. Please bug this."); } object oSpeaker = GetNearestObjectByTag(sSpeakerTag, oIPSpeaker); // DEBUG if ( GetIsObjectValid( oPC ) == FALSE ) PrettyError( "AttemptIPSConversation: oPC is not valid!" ); if ( GetIsObjectValid( oSpeaker ) == FALSE ) PrettyError( "AttemptIPSConversation: oSpeaker is not valid!" ); // Check if conditions are safe if ((GetIsIPSConversible(oPC, oIPSpeaker) == TRUE) && (GetIsIPSConversible(oSpeaker, oIPSpeaker) == TRUE)) { //PrettyMessage("Participants ready..."); // Stop the IPSpeaker SetIPSConversationPending(oIPSpeaker, FALSE); string sConversation = GetLocalString(oIPSpeaker, IPS_CONVERSATION); if (sConversation == "") { PrettyError("WARNING: gp_ipspeaker_hb: sConversation is not set. Attempting default conversation. Conversation may be missing."); } // Plot party, hide hostiles, save AI CombatCutsceneSetup(oPC); // Revive and remove bad effects MakeConversable(oPC, TRUE); MakeConversable(oSpeaker, FALSE); // Begin conversation ClearPartyActions(oPC, TRUE); //if (GetDistanceBetween(oPC, oSpeaker) > 20.0f) //{ // AssignCommand(oPC, JumpPartyToSpeaker(oPC, oSpeaker)); //} //else //{ //AssignCommand(oPC, JumpPartyToSpeaker(oPC, oPC)); //} //PrettyDebug("AttemptIPSpeaker: Conversation starting..."); AssignCommand(oSpeaker, ClearAllActions(TRUE)); AssignCommand(oSpeaker, ActionStartConversation(oPC, sConversation, FALSE, FALSE, TRUE, FALSE)); // Clean up when conversation ends //object oIPCleaner = CreateObject(OBJECT_TYPE_PLACEABLE, IPC_RESREF, GetLocation(oPC)); //AssignCommand(oIPCleaner, QueueCombatCutsceneCleanUp()); int bDeleteSelf = GetLocalInt(oIPSpeaker, IPS_DELETE_SELF); if (bDeleteSelf == TRUE) { SetPlotFlag(oIPSpeaker, FALSE); DelayCommand(2.0f, DestroyObject(oIPSpeaker)); } } } DelayCommand(0.5f, SetIPSLocked(0)); } // Check if a pending conversation is ready to play int GetIsIPSConversationPending(object oIPSpeaker=OBJECT_SELF) { return GetLocalInt(oIPSpeaker, IPS_PENDING); } // Set IPS_PENDING local var to flag a pending conversation as ready to play void SetIPSConversationPending(object oIPSpeaker=OBJECT_SELF, int bPending=TRUE) { SetLocalInt(oIPSpeaker, IPS_PENDING, bPending); } // Check if oObject is safe to conversate (valid, in area, not in conversation) // IPS conversation can start despite death or combat state int GetIsIPSConversible(object oObject, object oIPSpeaker=OBJECT_SELF) { // Verify oObject is valid if (GetIsObjectValid(oObject) == FALSE) { PrettyError( "GetIsIPSConversible: oObject is not valid" ); return (FALSE); } // Verify oObject and oIPSpeaker are in the same area if (GetArea(oIPSpeaker) != GetArea(oObject)) { PrettyError( "GetIsIPSConversible: " + GetName( oObject ) + " is not in IPS' area" ); return (FALSE); } // Verify oObject (or PC party) is not already in a conversation if ((GetIsPC(oObject) == TRUE) && (GetIsPartyInConversation(oObject) == TRUE)) { PrettyError( "GetIsIPSConversible: oObject or a party member is already in a conversation" ); return (FALSE); } else if (IsInConversation(oObject) == TRUE) { PrettyError( "GetIsIPSConversible: oObject is in a conversation" ); return (FALSE); } // Solid gold! return (TRUE); } // ginc_item /* Item/Inventory/Store related functions */ // ChazM 9/29/05 // ChazM 10/12/05 - added Remember, Restore, and Give family of functions // ChazM 1/20/06 - added EquipRandomArmorFromInventory(), ListInventory(), GetInventoryItemOfBaseType() // ChazM 1/31/06 - included "x2_inc_itemprop", added GetItemCategory(), GetIsItemCategory(), GetIsWeapon(), GetIsShield(), GetIsArmorOrShield() // ChazM 3/15/06 - added TransferItem(), modified GiveEquippedItem(), GiveAllInventory(), GiveEverything() // ChazM 6/27/06 - added UnequipSlot() // ChazM 6/29/06 - fixed UnequipSlot() // ChazM 8/8/06 - Moved GetState() & SetState() to ginc_math // ChazM 8/18/06 - added GetSlotOfEquippedItem(), GetIsCreatureSlot() // ChazM 8/30/06 - added N2_GetNPCEasyMark(), N2_AppraiseOpenStore() // ChazM 9/29/06 - Modified GetItemCategory() - now uses IP functions #include "ginc_debug" #include "x2_inc_itemprop" #include "ginc_math" // void main(){} const string LAST_SLOT_NUM = "LastSlotNum"; const string LAST_SLOT_OBJ = "LastSlotObj"; // item categories - weapon, armor/shield, other const int ITEM_CATEGORY_NONE = 0; const int ITEM_CATEGORY_WEAPON = 1; const int ITEM_CATEGORY_ARMOR_SHIELD = 2; const int ITEM_CATEGORY_OTHER = 4; const int ITEM_CATEGORY_ALL = 7; //------------------------------------------------- // Function Prototypes //------------------------------------------------- // item functions int GetIsItemEquipped(string sItemTag, object oCreature, int bExactMatch = TRUE); int GetPartyMemberHasEquipped(string sItemTag, object oPartyMember, int bPCOnly=TRUE, int bExactMatch = TRUE); int RemoveItem (object oCreature, string sItemTag); void CreateItemOnFaction(object oPC, string sItemResRef, int bPCOnly=TRUE); void EquipNewItem(object oTarget, string sItemResRef, int iEquipSlot); void DoEquipmentUpgrade(string sTargetTag, string sItemResRef, int iEquipSlot); void TransferItem(object oGiver, object oReceiver, object oInventoryItem); void RememberEquippedItem(object oOwner, int iSlot); void RememberEquippedItems(object oOwner); void RestoreEquippedItem(object oOwner, object oInventoryItem, int bReset=TRUE); void RestoreEquippedItems(object oOwner, int bReset=TRUE); void UnequipSlot(object oOwner, int iSlot); void GiveEquippedItem(object oGiver, object oReceiver, int iSlot); void GiveAllEquippedItems(object oGiver, object oReceiver); void GiveAllInventory(object oGiver, object oReceiver); void GiveEverything(object oGiver, object oReceiver); int GetItemCategory(object oItem); int GetIsItemCategory(object oItem, int iItemCategory); int GetIsWeapon(object oItem); int GetIsShield(object oItem); int GetIsArmorOrShield(object oItem); int GetSlotOfEquippedItem(object oItem, object oCreature); int GetIsCreatureSlot(int iSlot); // *** Store related int N2_GetNPCEasyMark(object oTarget); void N2_AppraiseOpenStore(object oStore, object oPC, int nBonusMarkUp = 0, int nBonusMarkDown = 0); //------------------------------------------------- // Function Definitions //------------------------------------------------- // returns true if item equipped // sItemTag - tag of the item to look for // oPartyMember - creature whose equipment is to be searched. // bExactMatch - whether or not to search tags with exact or partial matches int GetIsItemEquipped(string sItemTag, object oCreature, int bExactMatch = TRUE) { object oItem; string sFoundTag; int nSlot; for (nSlot=0; nSlot= 0) DelayCommand(0.5, AssignCommand(oTarget, ActionEquipItem(oItem, iEquipSlot))); } // give all w/ sTargetTag, specified equipment and put in specified slot void DoEquipmentUpgrade(string sTargetTag, string sItemResRef, int iEquipSlot) { int i = 0; object oTarget = GetObjectByTag(sTargetTag, i); while (GetIsObjectValid(oTarget)) { // PrintString("Equiping NPC " + GetName(oTarget) + " - index " + IntToString(i)); EquipNewItem(oTarget, sItemResRef, iEquipSlot); oTarget = GetObjectByTag(sTargetTag, ++i); } DebugMessage("Total number of creatures updated: " + IntToString(i)); } // store info on item about current owner and slot equipped void RememberEquippedItem(object oOwner, int iSlot) { object oInventoryItem = GetItemInSlot(iSlot, oOwner); if (oInventoryItem != OBJECT_INVALID) { SetLocalInt(oInventoryItem, LAST_SLOT_NUM, iSlot); SetLocalObject(oInventoryItem, LAST_SLOT_OBJ, oOwner); } } // store info on all equipped items of owner void RememberEquippedItems(object oOwner) { int iSlot; for (iSlot = 0; iSlot < NUM_INVENTORY_SLOTS; iSlot++) { RememberEquippedItem(oOwner, iSlot); } } // restore item to slot last remembered void RestoreEquippedItem(object oOwner, object oInventoryItem, int bReset=TRUE) { int iSlot = GetLocalInt(oInventoryItem, LAST_SLOT_NUM); //object oOrigOwner = GetLocalObject(oInventoryItem, LAST_SLOT_OBJ); if (iSlot > 0) { AssignCommand(oOwner, ActionEquipItem(oInventoryItem, iSlot)); if (bReset) { DeleteLocalInt(oInventoryItem, LAST_SLOT_NUM); DeleteLocalObject(oInventoryItem, LAST_SLOT_OBJ); } } } // Restore all inventory items to equipment slot last remembered (if any) void RestoreEquippedItems(object oOwner, int bReset=TRUE) { object oInventoryItem = GetFirstItemInInventory(oOwner); object oLeftHandItem; int iSlot; while (oInventoryItem != OBJECT_INVALID) { iSlot = GetLocalInt(oInventoryItem, LAST_SLOT_NUM); //EPF 8/29/06 left hand must be equipped after right. Otherwise the engine // will shift it to the right hand slot automatically. if(iSlot != INVENTORY_SLOT_LEFTHAND) { RestoreEquippedItem(oOwner, oInventoryItem, bReset); oInventoryItem = GetNextItemInInventory(oOwner); } else { oLeftHandItem = oInventoryItem; } } if(GetIsObjectValid(oLeftHandItem)) { RestoreEquippedItem(oOwner, oLeftHandItem, bReset); } } // unequip item in specified slot, if any void UnequipSlot(object oOwner, int iSlot) { object oInventoryItem = GetItemInSlot(iSlot, oOwner); if (oInventoryItem != OBJECT_INVALID) { AssignCommand(oOwner, ActionUnequipItem(oInventoryItem)); } } // passing around carried stuff. void GiveEquippedItem(object oGiver, object oReceiver, int iSlot) { if (GetObjectType(oGiver) != OBJECT_TYPE_CREATURE) { PrettyError("GiveEquippedItem(): Equipped Item Giver must be a creature!"); return; } object oInventoryItem = GetItemInSlot(iSlot, oGiver); if (oInventoryItem != OBJECT_INVALID) { AssignCommand(oGiver, ActionUnequipItem(oInventoryItem)); //AssignCommand(oReceiver, ActionTakeItem(oInventoryItem, oGiver)); //AssignCommand(oGiver, ActionGiveItem(oInventoryItem, oReceiver)); TransferItem(oGiver, oReceiver, oInventoryItem); } } void GiveAllEquippedItems(object oGiver, object oReceiver) { int iSlot; for (iSlot = 0; iSlot < NUM_INVENTORY_SLOTS; iSlot++) { GiveEquippedItem(oGiver, oReceiver, iSlot); } } // Transfer an item from giver to receiver. // objects lack an action queue, so void TransferItem(object oGiver, object oReceiver, object oInventoryItem) { // placeable give/take item commands are most dependable if (GetObjectType(oReceiver) == OBJECT_TYPE_PLACEABLE) { // the receiver is a creature, so he can be assigned ActionTakeItem() commands to his queue AssignCommand(oReceiver, ActionTakeItem(oInventoryItem, oGiver)); } else //if ((GetObjectType(oGiver) == OBJECT_TYPE_PLACEABLE) { // if both are creatures, giving item better than taking since taking causes movement. AssignCommand(oGiver, ActionGiveItem(oInventoryItem, oReceiver)); } } // are bags passed as full bags, or traversed? // inventory space limits? // stacked items? void GiveAllInventory(object oGiver, object oReceiver) { //if ((GetObjectType(oGiver) != OBJECT_TYPE_CREATURE) && (GetObjectType(oReceiver) != OBJECT_TYPE_CREATURE)) //{ // PrettyError("GiveAllInventory(): At least one of Giver or Receiver must be a creature."); // return; //} object oInventoryItem = GetFirstItemInInventory(oGiver); while (oInventoryItem != OBJECT_INVALID) { TransferItem(oGiver, oReceiver, oInventoryItem); //AssignCommand(oGiver, ActionGiveItem(oInventoryItem, oReceiver)); oInventoryItem = GetNextItemInInventory(oGiver); } } // give gold, equipped items, and inventory void GiveEverything(object oGiver, object oReceiver) { if (GetObjectType(oGiver) != OBJECT_TYPE_CREATURE) { PrettyError("GiveEverything(): Everything Giver must be a creature!"); return; } int iGold = GetGold(oGiver);// Remove gold to crate AssignCommand(oReceiver, TakeGoldFromCreature(iGold, oGiver, FALSE)); GiveAllEquippedItems(oGiver, oReceiver); GiveAllInventory(oGiver, oReceiver); } // Return number of items of Base Type in inventory int CountInventoryItemsOfBaseType(int nBaseType, object oCreature=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oCreature); int iItemCount=0; while (GetIsObjectValid(oItem)) { if (GetBaseItemType(oItem) == nBaseType) { iItemCount++; } oItem = GetNextItemInInventory(oCreature); } return iItemCount; } object GetInventoryItemOfBaseType(int nBaseType, int nNth=1, object oCreature=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oCreature); int iItemCount=0; while (GetIsObjectValid(oItem)) { if (GetBaseItemType(oItem) == nBaseType) { iItemCount++; if (iItemCount == nNth) { //PrettyDebug("Found requested item in inventory: " + GetName(oItem)); return (oItem); } } oItem = GetNextItemInInventory(oCreature); } return OBJECT_INVALID; } // list items in inventory. Should work for placeables too. int ListInventory(object oCreature=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oCreature); int i; PrettyDebug("*** Items in the inventory of " + GetName(oCreature)); while (GetIsObjectValid(oItem)) { i++; PrettyDebug("Item " + IntToString(i) + ": " + GetName(oItem)); oItem = GetNextItemInInventory(oCreature); } return i; } // returns TRUE if an item was found int EquipRandomArmorFromInventory() { int bRet = FALSE; //PrettyDebug("Looking for something to change into"); int iCount = CountInventoryItemsOfBaseType(BASE_ITEM_ARMOR); int iChoice = Random(iCount)+1; object oArmor = GetInventoryItemOfBaseType(BASE_ITEM_ARMOR, iChoice); if (GetIsObjectValid(oArmor)) { bRet = TRUE; ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_CHEST)); ActionEquipItem(oArmor, INVENTORY_SLOT_CHEST); } return (bRet); } // **** Functions for Identifying Item Types // Is this a weapon of any type (including ammunition). int GetIsWeapon(object oItem) { return(IPGetIsMeleeWeapon(oItem) || IPGetIsRangedWeapon(oItem) || IPGetIsProjectile(oItem)); } // is this a shield? int GetIsShield(object oItem) { int iType = GetBaseItemType(oItem); int iRet = FALSE; switch (iType) { case BASE_ITEM_SMALLSHIELD : case BASE_ITEM_LARGESHIELD : case BASE_ITEM_TOWERSHIELD : iRet = TRUE; break; } return iRet; } // Is this armor or shield? int GetIsArmorOrShield(object oItem) { int iType = GetBaseItemType(oItem); return ((iType == BASE_ITEM_ARMOR) || GetIsShield(oItem)); } // Is item in specified (bit flag) category? int GetIsItemCategory(object oItem, int iItemCategory) { int iThisCategory = GetItemCategory(oItem); //int iRet = GetState(iThisCategory, iItemCategory); //PrettyDebug(GetName(oItem) + " is in Category " + IntToString(iThisCategory) + // " In passed category of [" + IntToString(iItemCategory) + "] = " + IntToString(iRet)); return (GetState(iThisCategory, iItemCategory)); } // Returns basic category which is includes weapon, armor, and other int GetItemCategory(object oItem) { int iRet; if (!GetIsObjectValid(oItem)) iRet = ITEM_CATEGORY_NONE; else if (GetIsWeapon(oItem)) iRet = ITEM_CATEGORY_WEAPON; else if (GetIsArmorOrShield(oItem)) iRet = ITEM_CATEGORY_ARMOR_SHIELD; else iRet = ITEM_CATEGORY_OTHER; /* int iType = GetBaseItemType(oItem); switch (iType) { // swords case BASE_ITEM_SHORTSWORD : case BASE_ITEM_LONGSWORD : case BASE_ITEM_TWOBLADEDSWORD : case BASE_ITEM_BASTARDSWORD : case BASE_ITEM_GREATSWORD : case BASE_ITEM_GREATAXE : case BASE_ITEM_KATANA : case BASE_ITEM_RAPIER : case BASE_ITEM_SCIMITAR : // axes case BASE_ITEM_DOUBLEAXE : case BASE_ITEM_BATTLEAXE : case BASE_ITEM_HANDAXE : case BASE_ITEM_DWARVENWARAXE : // flails case BASE_ITEM_LIGHTFLAIL : case BASE_ITEM_HEAVYFLAIL : // hammers case BASE_ITEM_WARHAMMER : case BASE_ITEM_LIGHTHAMMER : // maces case BASE_ITEM_DIREMACE : case BASE_ITEM_LIGHTMACE : // misc melee weapons case BASE_ITEM_HALBERD : case BASE_ITEM_DAGGER : case BASE_ITEM_KAMA : case BASE_ITEM_KUKRI : case BASE_ITEM_MORNINGSTAR : case BASE_ITEM_QUARTERSTAFF : case BASE_ITEM_SHORTSPEAR : case BASE_ITEM_SICKLE : case BASE_ITEM_SCYTHE : case BASE_ITEM_WHIP : case BASE_ITEM_CLUB : // creature weapons case BASE_ITEM_CSLASHWEAPON : case BASE_ITEM_CPIERCWEAPON : case BASE_ITEM_CBLUDGWEAPON : case BASE_ITEM_CSLSHPRCWEAP : // ranged reapons case BASE_ITEM_HEAVYCROSSBOW : case BASE_ITEM_LIGHTCROSSBOW : case BASE_ITEM_LONGBOW : case BASE_ITEM_SHORTBOW : case BASE_ITEM_SLING : case BASE_ITEM_DART : case BASE_ITEM_THROWINGAXE : case BASE_ITEM_GRENADE : case BASE_ITEM_SHURIKEN : // ammunition case BASE_ITEM_ARROW : case BASE_ITEM_BULLET : case BASE_ITEM_BOLT : iRet = ITEM_CATEGORY_WEAPON; break; // armor/shield case BASE_ITEM_ARMOR : case BASE_ITEM_SMALLSHIELD : case BASE_ITEM_LARGESHIELD : case BASE_ITEM_TOWERSHIELD : iRet = ITEM_CATEGORY_ARMOR_SHIELD; break; // equippable stuff case BASE_ITEM_HELMET : case BASE_ITEM_BELT : case BASE_ITEM_BOOTS : case BASE_ITEM_GLOVES : case BASE_ITEM_RING : case BASE_ITEM_AMULET : case BASE_ITEM_BRACER : case BASE_ITEM_CLOAK : // misc items case BASE_ITEM_MISCSMALL : case BASE_ITEM_MISCMEDIUM : case BASE_ITEM_MISCLARGE : case BASE_ITEM_MISCTALL : case BASE_ITEM_MISCWIDE : case BASE_ITEM_MISCTHIN : // magic items case BASE_ITEM_MAGICROD : case BASE_ITEM_MAGICSTAFF : case BASE_ITEM_MAGICWAND : case BASE_ITEM_SPELLSCROLL : case BASE_ITEM_POTIONS : // blank magic items case BASE_ITEM_BLANK_POTION : case BASE_ITEM_BLANK_SCROLL : case BASE_ITEM_BLANK_WAND : case BASE_ITEM_ENCHANTED_POTION : case BASE_ITEM_ENCHANTED_SCROLL : case BASE_ITEM_ENCHANTED_WAND : // mundane items case BASE_ITEM_HEALERSKIT : case BASE_ITEM_BOOK : case BASE_ITEM_SCROLL : case BASE_ITEM_TORCH : case BASE_ITEM_THIEVESTOOLS : case BASE_ITEM_TRAPKIT : case BASE_ITEM_KEY : case BASE_ITEM_LARGEBOX : case BASE_ITEM_CREATUREITEM : case BASE_ITEM_GOLD : case BASE_ITEM_GEM : // crafting items case BASE_ITEM_CRAFTMATERIALMED : case BASE_ITEM_CRAFTMATERIALSML : iRet = ITEM_CATEGORY_OTHER; break; } */ return (iRet); } // return slot item is equipped in on creature. -1 if not found int GetSlotOfEquippedItem(object oItem, object oCreature) { int iSlot; object oItemInSlot; for (iSlot=0; iSlot nPlayerSkillRank) { nState = STATE_FAILED; } else if (nNPCSkillRank < nPlayerSkillRank) { nState = STATE_WON; } else if (nNPCSkillRank == nPlayerSkillRank) { nState = STATE_TIE; } if (nState == STATE_FAILED ) { FloatingTextStrRefOnCreature(182468, oPC, FALSE); } else if (nState == STATE_WON) { FloatingTextStrRefOnCreature(182470, oPC, FALSE); } else if (nState == STATE_TIE) { FloatingTextStrRefOnCreature(182469, oPC, FALSE); } // * Hard cap of 30% max up or down if (nAdjust > 30) nAdjust = 30; if (nAdjust < -30) nAdjust = -30; // nBonusMarkUp is added to the stores default mark up percentage on items sold (-100 to 100) // (positive is good for player) // Effect on selling items is only half of effect on buying items. nBonusMarkUp = nBonusMarkUp + nAdjust/2; // nBonusMarkDown is added to the stores default mark down percentage on items bought (-100 to 100) // (negative is good for player) nBonusMarkDown = nBonusMarkDown - nAdjust; OpenStore(oStore, oPC, nBonusMarkUp, nBonusMarkDown); } // ginc_item_script /* include for item scripts */ // ChazM 9/8/06 // ChazM 9/12/06 added IsItemAcquiredByPartyMember() //#include "x2_inc_itemprop" #include "ginc_param_const" #include "ginc_vars" #include "ginc_debug" /* int SCRIPT_MODULE_ON_ACTIVATE_ITEM = 6; int SCRIPT_MODULE_ON_ACQUIRE_ITEM = 7; int SCRIPT_MODULE_ON_LOSE_ITEM = 8; int SCRIPT_MODULE_ON_EQUIP_ITEM = 15; int SCRIPT_MODULE_ON_UNEQUIP_ITEM = 16; */ //---------------------------------------------- // Prototypes //---------------------------------------------- int IsItemAquiredByPartyMember(); int IsItemMarkedAsDone(object oItem, int iFlag=0); void MarkItemAsDone(object oItem, int iFlag=0); //---------------------------------------------- // Functions //---------------------------------------------- // Can only be run use in an onAquire script. // Checks if the item was aquired by a member of a int IsItemAcquiredByPartyMember() { // Because a player can drag an item from a placeable "!s inventory directly onto a companion "!s portrait, // bypassing his own inventory. This means the onAquire event fires on an unpossessed companion, // who returns FALSE on the GetIsPC(). int iRet = FALSE; object oPC = GetModuleItemAcquiredBy(); //if (GetFactionEqual(GetFirstPC(), oPC)) // won't work in multi-party object oLeader = GetFactionLeader(oPC); // only PC parties have faction leaders. if (GetIsObjectValid(oLeader)) iRet = TRUE; return (iRet); } // Check if marked as done. // Optionally check if done for a specific flag // recommened Usage: IsItemMarkedAsDone(oItem, SCRIPT_MODULE_ON_ACQUIRE_ITEM) int IsItemMarkedAsDone(object oItem, int iFlag=0) { string sNVPName = GetDoneFlag(iFlag); string sNVPList = GetLastName(oItem); int iDoneOnce = StringToInt(GetNVPValue(sNVPList, sNVPName)); return (iDoneOnce); } // Set marked as done. // Optionally set as done for a specific flag // recommened Usage: MarkItemAsDone(oItem, SCRIPT_MODULE_ON_ACQUIRE_ITEM) void MarkItemAsDone(object oItem, int iFlag=0) { string sNVPName = GetDoneFlag(iFlag); string sNVPList = GetLastName(oItem); sNVPList = AppendUniqueToNVP(sNVPList, sNVPName, IntToString(TRUE)); SetLastName(oItem, sNVPList); } // to be removed /* int ItemScriptAcquireRunBefore(object oItem) { return (FALSE); } */ //void main(){} // ginc_journal /* journal/quest related functions */ // ChazM 9/28/05 // ChazM 9/29/05 added GetQuestXPPercentRewarded(), RewardCappedQuestXP(), RewardPartyQuestXP(), RewardPartyCappedQuestXP(), // renamed N2_Reward* functions, some temp functions // ChazM 7/26/06 Added AwardXP(), SendMessageToParty() #include "X0_I0_PARTYWIDE" #include "ginc_vars" #include "ginc_item" //void main() {} const string QPR_SUFFIX = "_XP_QPR"; // 2da table and column names const string TABLE_XP_AWARD = "k_xp_awards"; const string COL_XP = "XP"; const string COL_STR_REF = "DescStrRef"; const string COL_TEXT = "DescriptionText"; //------------------------------------------------- // Function Prototypes //------------------------------------------------- // Quest Info int GetIsJournalQuestAssigned(string sPlotID, object oCreature); int GetJournalQuestEntry(string sPlotID, object oCreature); int GetQuestXPPercentRewarded(object oPC, string sQuestTag); // Neverwinter 2 quest reward functions // non-party rewards int RewardCappedQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100, int iQuestXPPercentCap = 100); // party rewards void RewardPartyUniqueItem(object oPC, string sItemResRef); void RewardPartyItem(object oPC, string sItemResRef); void RewardPartyGold(object oPC, int iGold); void RewardPartyXP(object oPC, int iXP); int RewardPartyQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100); void RewardPartyCappedQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100, int iQuestXPPercentCap = 100); // special objective rewards with accompanying text from k_xp_awards.2da void AwardXP(object oPC, int iXPAwardID, int bWholeParty=TRUE); // From: X0_I0_PARTYWIDE //void GiveGoldToAllEqually(object oPC, int nGoldToDivide); //void GiveGoldToAll(object oPC, int nGold); //void GiveXPToAllEqually(object oPC, int nXPToDivide); //void GiveXPToAll(object oPC, int nXP); //------------------------------------------------- // Function Definitions //------------------------------------------------- //---------------------------------------- // Quest Info //---------------------------------------- // Determine if Quest sPlotID is not 0 (assumes non-zero as having been assigned). int GetIsJournalQuestAssigned(string sPlotID, object oCreature) { return (GetJournalQuestEntry(sPlotID, oCreature) > 0); } /* // Determine if Quest sPlotID is not 0, but has not reached an endpoint (entryID non-zero and non-endpoint). GetIsJournalQuestActive(string sPlotID, object oCreature) // Determine if Quest sPlotID has reached any endpoint. GetIsJournalQuestFinished(string sPlotID, object oCreature) */ int GetJournalQuestEntry(string sPlotID, object oCreature) { int iQuestEntry = GetLocalInt(oCreature, "NW_JOURNAL_ENTRY" + sPlotID); return (iQuestEntry); } // get the percent rewarded so far to this PC for this quest int GetQuestXPPercentRewarded(object oPC, string sQuestTag) { string sXPQuestPercentRewarded = sQuestTag + QPR_SUFFIX; int iQuestXPPercentRewarded = GetLocalInt(oPC, sXPQuestPercentRewarded); return (iQuestXPPercentRewarded); } //---------------------------------------- // Quest Rewards (non-party) //---------------------------------------- // reward xp amount to single player, subject to cap // return amount awarded int RewardCappedQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100, int iQuestXPPercentCap = 100) { int iQuestXPPercentRewarded = GetQuestXPPercentRewarded(oPC, sQuestTag); // reduce reward to cap amount if necessary if ((iQuestXPPercentRewarded + iQuestXPPercent) > iQuestXPPercentCap) { iQuestXPPercent = iQuestXPPercentCap - iQuestXPPercentRewarded; if (iQuestXPPercent < 0) return (0); } string sXPQuestPercentRewarded = sQuestTag + QPR_SUFFIX; int iQuestXPReward = (GetJournalQuestExperience(sQuestTag) * iQuestXPPercent)/100; GiveXPToCreature(oPC, iQuestXPReward); ModifyLocalInt(oPC, sXPQuestPercentRewarded, iQuestXPPercent); return (iQuestXPReward); } //---------------------------------------- // Party Quest Rewards //---------------------------------------- // reward w/ plot item - currently gives to all players so all can advance plot on their own void RewardPartyUniqueItem(object oPC, string sItemResRef) { CreateItemOnFaction(oPC, sItemResRef); } // reward player w/ item - currently gives only one of the item - party must decide how to split it up. void RewardPartyItem(object oPC, string sItemResRef) { CreateItemOnObject(sItemResRef, oPC); } // reward player w/ Gold - currently everyone gets full amount void RewardPartyGold(object oPC, int iGold) { GiveGoldToAll(oPC, iGold); //GiveGoldToAllEqually(oPC, iGold); } // reward player w/ XP - currently everyone gets full amount // this should be used only for non-quest related XP rewards void RewardPartyXP(object oPC, int iXP) { GiveXPToAll(oPC, iXP); //GiveXPToAllEqually(oPC, iXP); } // Give XP rewards for quest. Amount given is tracked, but there is no cap. // return amount awarded int RewardPartyQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100) { // Give the party XP int iQuestXPReward = (GetJournalQuestExperience(sQuestTag) * iQuestXPPercent)/100; GiveXPToAll(oPC, iQuestXPReward); // track amount given string sXPQuestPercentRewarded = sQuestTag + QPR_SUFFIX; ModifyLocalIntOnFaction(oPC, sXPQuestPercentRewarded, iQuestXPPercent); return (iQuestXPReward); } // reward xp amount to party, subject to cap void RewardPartyCappedQuestXP(object oPC, string sQuestTag, int iQuestXPPercent = 100, int iQuestXPPercentCap = 100) { object oPartyMem = GetFirstFactionMember(oPC, TRUE); while (GetIsObjectValid(oPartyMem)) { RewardCappedQuestXP(oPartyMem, sQuestTag, iQuestXPPercent, iQuestXPPercentCap); oPartyMem = GetNextFactionMember(oPC, TRUE); } } void SendMessageToParty(object oPC, string sTlkText) { object oPartyMember = GetFirstFactionMember(oPC, TRUE); // PC's only while(GetIsObjectValid(oPartyMember) == TRUE) { SendMessageToPC(oPartyMember, sTlkText); // GiveXPToCreature(oPartyMember, iXP); oPartyMember = GetNextFactionMember(oPC, TRUE); // PC's only } } void AwardXP(object oPC, int iXPAwardID, int bWholeParty=TRUE) { string sWarnText; int iXP = StringToInt(Get2DAString(TABLE_XP_AWARD, COL_XP, iXPAwardID)); int iStringRef = StringToInt(Get2DAString(TABLE_XP_AWARD, COL_STR_REF, iXPAwardID)); string sTlkText = GetStringByStrRef(iStringRef); //string sText = Get2DAString(TABLE_XP_AWARD, COL_TEXT, iXPAwardID); if (iStringRef == 0) { sWarnText = "DescStrRef not defined in k_xp_awards.2da for Row # " + IntToString(iXPAwardID); PrettyError(sWarnText); } else if (sTlkText == "") { sWarnText = "String # " + IntToString(iStringRef) + " is empty or not found in Tlk table as specified in k_xp_awards.2da for Row # " + IntToString(iXPAwardID); PrettyError(sWarnText); } if (bWholeParty) { SendMessageToParty(oPC, sTlkText); RewardPartyXP(oPC, iXP); } else { SendMessageToPC(oPC, sTlkText); GiveXPToCreature(oPC, iXP); } } // From: X0_I0_PARTYWIDE /********* REWARD FUNCTIONS ******************/ /* // Given a gold amount, divides it equally among the party members // of the given PC's party. // None given to associates. void GiveGoldToAllEqually(object oPC, int nGoldToDivide); // Given a gold amount, gives that amount to all party members // of the given PC's party. // None given to associates. void GiveGoldToAll(object oPC, int nGold); // Given an XP amount, divides it equally among party members // of the given PC's party. // None given to associates. // Tip: use with GetJournalQuestExperience() to // get the amount of XP assigned to that quest in the // journal. void GiveXPToAllEqually(object oPC, int nXPToDivide); // Given an XP amount, gives that amount to all party members // of the given PC's party. // None given to associates. // Tip: use with GetJournalQuestExperience() // get the amount of XP assigned to that quest in the // journal. void GiveXPToAll(object oPC, int nXP); */ // ginc_math /* Math related functions */ // ChazM 9/22/05 // ChazM 10/21/05 - added IsFloatNearInt() // DBR - 2/13/06 - Adding optional parameter of precision to RandomFloat() // BMA-OEI 5/4/06 - Added RandomFloatBetween(), RandomIntBetween() // BMA/CGAW 5/18/06 - Updated RandomFloat(), RandomFloatBetween() // ChazM 8/8/06 - Added SetLocalIntState(), GetLocalIntState(), SetState(), GetState() // BMA-OEI 10/09/06 - Added GetHexStringDigitValue(), HexStringToInt() //void main() {} #include "ginc_debug" const float EPSILON = 0.00001f; //------------------------------------------------- // Function Prototypes //------------------------------------------------- float RandomDelta(float fMagnitude); float RandomFloat(float fNum); float RandomFloatBetween( float fFloatA, float fFloatB=0.000f ); int RandomIntBetween( int nIntA, int nIntB=0 ); location GetNearbyLocation(location lTarget, float fDistance, float fFacingNoise=0.0f); int IsIntInRange(int iVar, int iMin, int iMax); int ScaleInt (int iNum, float fNum); int IsFloatNearInt(float fValue, int iValue); void SetLocalIntState(object oTarget, string sVariable, int iBitFlags, int bSet = TRUE); int GetLocalIntState(object oTarget, string sVariable, int iBitFlags); int SetState(int iValue, int iBitFlags, int bSet = TRUE); int GetState(int iValue, int iBitFlags); // Return ASCII value of hexadecimal digit sHexDigit // * Returns -1 if sHexDigit is not a valid hex digit (0-aA) int GetHexStringDigitValue( string sHexDigit ); // Return integer value of hexadecimal string sHexString // * Can convert both "0x????" and "????" where "?" is a hex digit int HexStringToInt( string sHexString ); //------------------------------------------------- // Function Definitions //------------------------------------------------- // gives a random number between -fMagnitude and fMagnitude // preserve 2 decimal places float RandomDelta(float fMagnitude) { float fRet = IntToFloat(Random(FloatToInt(fMagnitude * 100.0f)))/100.0f; if (d2()==1) fRet = -fRet; return (fRet); } // Returns a random float between fNum and 0. See RandomFloatBetween() for additional information. float RandomFloat(float fNum) { float fRet = RandomFloatBetween( fNum ); return (fRet); } // Return a random float value between fFloatA and fFloatB // NOTE: Maximum accuracy is produced when the difference between A and B is no more than: // 32,767/10^N, where N = The number of contiguous digits to the right of the decimal point that are important. // For instance, if the float should be accurate for three decimal places: xx.000, then to have maximum // accuracy, the difference between A and B shouldn't be more than 32,767/10^3, or 32.767. float RandomFloatBetween( float fFloatA, float fFloatB=0.000f ) { float fLesserFloat; float fGreaterFloat; float fDifference; float fRandomFloat; float fMultiplier = IntToFloat( Random( 32767 ) ) / 32766.f; if ( fFloatA <= fFloatB ) { fLesserFloat = fFloatA; fGreaterFloat = fFloatB; } else { fLesserFloat = fFloatB; fGreaterFloat = fFloatA; } fDifference = fGreaterFloat - fLesserFloat; fRandomFloat = ( fDifference * fMultiplier ) + fLesserFloat; return ( fRandomFloat ); } // Return a random int value between nIntA and nIntB int RandomIntBetween( int nIntA, int nIntB=0 ) { int nLesserInt; int nGreaterInt; int nDifference; int nRandomInt; if ( nIntA <= nIntB ) { nLesserInt = nIntA; nGreaterInt = nIntB; } else { nLesserInt = nIntB; nGreaterInt = nIntA; } nDifference = nGreaterInt - nLesserInt; nRandomInt = Random( nDifference + 1 ) + nLesserInt; return ( nRandomInt ); } // get a location fDistance units from lTarget // location lTarget - target location // float fDistance - max random distance location GetNearbyLocation(location lTarget, float fDistance, float fFacingNoise=0.0f) { vector vOld = GetPositionFromLocation(lTarget); float x = RandomDelta(fDistance); float y = RandomDelta(fDistance); vector vNew = vOld + Vector(x, y); float fNewFacing = GetFacingFromLocation(lTarget) + RandomDelta(fFacingNoise); if (fNewFacing < 0.0f) fNewFacing = fNewFacing + 360.0f; else if (fNewFacing > 360.0f) fNewFacing = fNewFacing - 360.0f; location lNewLocation = Location (GetAreaFromLocation(lTarget), vNew, fNewFacing); return lNewLocation; } int IsIntInRange(int iVar, int iMin, int iMax) { return((iVar >= iMin) && (iVar <= iMax)); } // multiply int by float and return resulting int part int ScaleInt (int iNum, float fNum) { return (FloatToInt(IntToFloat(iNum) * fNum)); } int IsFloatNearInt(float fValue, int iValue) { //int iRet = FALSE; float fCompareValue = IntToFloat(iValue); if (fValue > fCompareValue + EPSILON) return (FALSE); if (fValue < fCompareValue - EPSILON) return (FALSE); return (TRUE); } // sets the bit flags on or off in the local int void SetLocalIntState(object oTarget, string sVariable, int iBitFlags, int bSet = TRUE) { int iValue = GetLocalInt(oTarget, sVariable); int iNewValue = SetState(iValue, iBitFlags, bSet); SetLocalInt(oTarget, sVariable, iNewValue); } // returns TRUE or FALSE // if multiple flags, will return true if any of iBitFlags are true. int GetLocalIntState(object oTarget, string sVariable, int iBitFlags) { int iValue = GetLocalInt(oTarget, sVariable); return (GetState(iValue, iBitFlags)); } // sets state of iBitFlags in iValue and returns new value. // if multiple flags, all will be modified int SetState(int iValue, int iBitFlags, int bSet = TRUE) { if(bSet == TRUE) { iValue = iValue | iBitFlags; } else if (bSet == FALSE) { iValue = iValue & ~iBitFlags; } return (iValue); } // returns state of iBitFlag in iValue. // if multiple flags, will return true if any are true. int GetState(int iValue, int iBitFlags) { return (iValue & iBitFlags); } // Return ASCII value of hexadecimal digit sHexDigit // * Returns -1 if sHexDigit is not a valid hex digit (0-aA) int GetHexStringDigitValue( string sHexDigit ) { int nValue = CharToASCII( sHexDigit ); if ( ( nValue >= 48 ) && ( nValue <= 57 ) ) // 0-9 [0x30-0x39] { return ( nValue - 48 ); } else if ( ( nValue >= 65 ) && ( nValue <= 70 ) ) // A-F [0x41-0x46] { return ( nValue - 55 ); } else if ( ( nValue >= 97 ) && ( nValue <= 102 ) ) // a-f [0x61-0x66] { return ( nValue - 87 ); } else { return ( -1 ); } } // Return integer value of hexadecimal string sHexString // * Can convert both "0x????" and "????" where "?" is a hex digit int HexStringToInt( string sHexString ) { int nStringLen = GetStringLength( sHexString ); int nReturn = 0; if ( nStringLen > 0 ) { int nPos = 0; // Check for "0x" prefix if ( nStringLen >= 2 ) { if ( GetSubString( sHexString, 0, 2 ) == "0x" ) { nPos = 2; } } string sChar; int nChar; // For length of hex string while ( nPos < nStringLen ) { // Get digit at position nPos sChar = GetSubString( sHexString, nPos, 1 ); nChar = GetHexStringDigitValue( sChar ); if ( nChar != -1 ) { // "bitshift left 4", OR nChar nReturn = ( nReturn << 4 ) | nChar; } else { // Invalid hex digit found break; } nPos = nPos + 1; } } return ( nReturn ); } // ginc_misc /* Miscellaneous useful functions */ // ChazM 3/4/05 // ChazM 5/5/05 added ForceExit() and SpawnCreatureAtWP() // BMA 5/12/05 added exact/partial param to GetIsItemEquipped(), GetPartyMemberHasEquipped() // EPF 6/9/05 ForceExit now uses GetTarget() // ChazM 6/14/05 added PCTriggeredOnce() // ChazM 7/7/05 added this comment // ChazM 8/16/05 modified SpawnCreatureAtWP // ChazM 8/22/05 added N2_RewardPlotItem(), N2_RewardItem(), N2_RewardXP(), N2_RewardGold(), and GiveItemToAll(), included X0_I0_PARTYWIDE // ChazM 9/17/05 added SpawnPlaceableAtWP(), SpawnPlaceablesAtWPs(), SpawnObjectAtWP(), SpawnObjectsAtWPs(), // GetNumberOfObjectsInArea(), GetRandomObjectInArea(), DebugMessage() // ChazM 9/22/05 moved DebugMessage() to ginc_debug and added as an include. // ChazM 9/28/05 moved N2_RewardPlotItem(), N2_RewardItem(), N2_RewardXP(), N2_RewardGold(), and GiveItemToAll() to "ginc_journal" - now included // ChazM 9/29/05 moved most funtions to other includes and added references to 2 new includes // ChazM 10/01/05 moved IsMarkedAsDone() and MarkAsDone() to ginc_vars // FAB 10/14/05 bullet-proofing ForceExit so you can't talk to someone running away // EPF 6/20/06 ForceExit turns off plot flag. // ChazM 6/22/06 ForceExit turns on destroyable flag. // DBR 7/18/06 - Destroyable flag needed an AssignCommand() for ForceExit(). // BMA-OEI 8/09/06 -- Added GetPCAverageXP() // ChazM 9/18/06 - included ginc_actions, updated ForceExit() to reference ActionForceExit() in ginc_actions. // dependent includes #include "ginc_param_const" // has ActionForceExit() #include "ginc_actions" // convenience only (non-dependent) includes #include "ginc_journal" #include "ginc_object" //void main(){} //------------------------------------------------- // Function Prototypes //------------------------------------------------- object GetAnyPCBeing(); void ForceExit(string sCreatureTag, string sWPTag, int bRun=FALSE); int PCTriggeredOnce(); // used for typical PC only triggers once triggers // Returns average XP of PCs int GetPCAverageXP(); //------------------------------------------------- // Function Definitions //------------------------------------------------- // Find first party member character controlled by a Player object GetAnyPCBeing() { object oPC = GetFirstPC(); object oMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oMember) == TRUE) { // If oMember is controlled by a player, return. if (GetIsPC(oMember) == TRUE) return (oMember); oMember = GetNextFactionMember(oPC, FALSE); } return (OBJECT_INVALID); } // Force creature w/ Tag sCreatureTag to move to exit WP and destroy self or despawn if roster member void ForceExit(string sCreatureTag, string sWPTag, int bRun=FALSE) { object oCreature = GetTarget(sCreatureTag); AssignCommand(oCreature, ActionForceExit(sWPTag, bRun)); } //---------------------------------------- // Trigger Related //---------------------------------------- // Used for typical PC Triggers where trigger only runs once for the PC. // Don't put more conditions after this call, since this will only return success once. int PCTriggeredOnce() { object oPC = GetEnteringObject(); // check conditions if (IsMarkedAsDone()) return TRUE; if (!GetIsPC(oPC)) return TRUE; MarkAsDone(); return FALSE; } // Returns average XP of all PCs in server int GetPCAverageXP() { int nXP = 0; int nPCs = 0; object oPC = GetFirstPC(); while ( GetIsObjectValid(oPC) == TRUE ) { nXP = nXP + GetXP( oPC ); nPCs = nPCs + 1; oPC = GetNextPC(); } return ( nXP / nPCs ); } // ginc_object /* object (creature and placeable) related functions */ // ChazM 9/29/05 // ChazM 9/30/05 added DestroyAllWithTag(), GetNumberOfObjects(), modified functions implementations and // added optional param bThisAreaOnly to SpawnCreaturesAtWPs, SpawnPlaceablesAtWPs and SpawnObjectsAtWPs // BDF 10/10/05: added PlaceObjectAtTag(), PlaceCreatureAtTag(), PlacePlaceableAtTag(), and PlaceItemAtTag() //void main (){} //------------------------------------------------- // Function Prototypes //------------------------------------------------- #include "ginc_param_const" // Needed for GetTarget() #include "ginc_debug" // Needed for ErrorMessage() object SpawnCreatureAtWP(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag=""); object SpawnPlaceableAtWP(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag=""); object SpawnObjectAtWP(int nObjectType, string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag=""); int SpawnCreaturesAtWPs(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="", int bThisAreaOnly=TRUE); int SpawnPlaceablesAtWPs(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="", int bThisAreaOnly=TRUE); int SpawnObjectsAtWPs(int nObjectType, string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="", int bThisAreaOnly=TRUE); int DestroyAllWithTag(string sTag, int bThisAreaOnly=FALSE); int GetNumberOfObjects(string sTag, int bThisAreaOnly=FALSE); int GetNumberOfObjectsInArea(string sTag); object GetRandomObjectInArea(string sTag); object PlaceObjectAtTag( int iObjectType, string sObjectTag, string sDestinationTag, string sObjectResRef ); object PlaceCreatureAtTag( string sCreatureTag, string sDestinationTag, string sCreatureResRef ); object PlacePlaceableAtTag( string sPlaceableTag, string sDestinationTag, string sPlaceableResRef ); object PlaceItemAtTag( string sItemTag, string sDestinationTag, string sItemResRef ); //------------------------------------------------- // Function Definitions //------------------------------------------------- // Spawn in creature sTemplate at the location of the waypoint with tag sWPTag. object SpawnCreatureAtWP(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="") { return(SpawnObjectAtWP(OBJECT_TYPE_CREATURE, sTemplate, sWPTag, bUseAppearAnimation, sNewTag)); } // Spawn in placeable sTemplate at the location of the waypoint with tag sWPTag. object SpawnPlaceableAtWP(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="") { return(SpawnObjectAtWP(OBJECT_TYPE_PLACEABLE, sTemplate, sWPTag, bUseAppearAnimation, sNewTag)); } // Spawn in creature sTemplate at the location of the waypoint with tag sWPTag. object SpawnObjectAtWP(int nObjectType, string sTemplate, string sWPTag, int bUseAppearAnimation=FALSE, string sNewTag="") { object oObject = OBJECT_INVALID; //object oWP = GetWaypointByTag(sWPTag); object oWP = GetObjectByTag(sWPTag); if (GetIsObjectValid(oWP) == TRUE) { location lWP = GetLocation(oWP); oObject = CreateObject(nObjectType, sTemplate, lWP, bUseAppearAnimation, sNewTag); if (!GetIsObjectValid(oObject)) { PrintString ("SpawnObjectAtWP: " + " Failed! " + sTemplate + "@" + sWPTag); } } else { PrintString ("SpawnObjectAtWP: " + " Waypoint invalid! " + sTemplate + "@" + sWPTag); } return (oObject); } // spawns creature at each wp with specified tag int SpawnCreaturesAtWPs(string sTemplate, string sWPTag, int bUseAppearAnimation=FALSE, string sNewTag="", int bThisAreaOnly=TRUE) { return(SpawnObjectsAtWPs(OBJECT_TYPE_CREATURE, sTemplate, sWPTag, bUseAppearAnimation, sNewTag, bThisAreaOnly)); } // spawns placeable at each wp with specified tag int SpawnPlaceablesAtWPs(string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="", int bThisAreaOnly=TRUE) { return(SpawnObjectsAtWPs(OBJECT_TYPE_PLACEABLE, sTemplate, sWPTag, bUseAppearAnimation, sNewTag, bThisAreaOnly)); } // spawns creature at each wp with specified tag int SpawnObjectsAtWPs(int nObjectType, string sTemplate, string sWPTag, int bUseAppearAnimation = FALSE, string sNewTag="", int bThisAreaOnly=TRUE) { int i = 0; object oTargetWP = GetObjectByTag(sWPTag, i); location lTargetWP; object oThisArea = GetArea(OBJECT_SELF); while (GetIsObjectValid(oTargetWP)) { if (bThisAreaOnly && (GetArea(oTargetWP) != oThisArea)) continue; lTargetWP = GetLocation(oTargetWP); CreateObject(nObjectType, sTemplate, lTargetWP, bUseAppearAnimation, sNewTag); i++; oTargetWP = GetObjectByTag(sWPTag,i); } //PrintString ("SpawnObjectsAtWPs: Created " + IntToString(i) + " of resref " + sTemplate); return(i); } // returns number destroyed int DestroyAllWithTag(string sTag, int bThisAreaOnly=FALSE) { int i = 0; object oObject = GetObjectByTag(sTag, i); object oThisArea = GetArea(OBJECT_SELF); while (GetIsObjectValid(oObject)) { if (bThisAreaOnly && (GetArea(oObject) != oThisArea)) break; DestroyObject(oObject); oObject = GetObjectByTag(sTag, ++i); } return (i); } int GetNumberOfObjects(string sTag, int bThisAreaOnly=FALSE) { int i = 0; object oObject = GetObjectByTag(sTag, i); object oThisArea = GetArea(OBJECT_SELF); while (GetIsObjectValid(oObject)) { if (bThisAreaOnly && (GetArea(oObject) != oThisArea)) break; oObject = GetObjectByTag(sTag, ++i); } return (i); } int GetNumberOfObjectsInArea(string sTag) { return (GetNumberOfObjects(sTag, TRUE)); /* int i = 1; object oTarget = GetNearestObjectByTag(sTag, OBJECT_SELF, i); while (GetIsObjectValid(oTarget)) { oTarget = GetNearestObjectByTag(sTag, OBJECT_SELF, ++i); } return (--i); */ } object GetRandomObjectInArea(string sTag) { int iNumObjects = GetNumberOfObjectsInArea(sTag); int iRandomIndex = Random(iNumObjects) + 1; return (GetNearestObjectByTag(sTag, OBJECT_SELF, iRandomIndex)); } object PlaceObjectAtTag( int iObjectType, string sObjectTag, string sDestinationTag, string sObjectResRef ) { object oObject = GetTarget( sObjectTag ); object oDest = GetTarget( sDestinationTag ); location lDest; if ( !GetIsObjectValid(oDest) ) { ErrorMessage( "Passed invalid destination tag to PlaceObjectAtTag" ); return OBJECT_INVALID; } else lDest = GetLocation( oDest ); if ( GetIsObjectValid(oObject) ) { AssignCommand( oObject, JumpToObject(oDest) ); return oObject; } else { if ( sObjectResRef != "" ) { return CreateObject( iObjectType, sObjectResRef, lDest, FALSE, sObjectTag ); } else { ErrorMessage( "Passed invalid object resref to PlaceObjectAtTag" ); return OBJECT_INVALID; } } return OBJECT_INVALID; } object PlaceCreatureAtTag( string sCreatureTag, string sDestinationTag, string sCreatureResRef ) { return PlaceObjectAtTag( OBJECT_TYPE_CREATURE, sCreatureTag, sDestinationTag, sCreatureResRef ); } object PlacePlaceableAtTag( string sPlaceableTag, string sDestinationTag, string sPlaceableResRef ) { return PlaceObjectAtTag( OBJECT_TYPE_PLACEABLE, sPlaceableTag, sDestinationTag, sPlaceableResRef ); } object PlaceItemAtTag( string sItemTag, string sDestinationTag, string sItemResRef ) { return PlaceObjectAtTag( OBJECT_TYPE_ITEM, sItemTag, sDestinationTag, sItemResRef ); } // ginc_param_const /* Include file for interesting params and converting ints to constants. */ // 3/10/05 ChazM // 4/22/05 ChazM - added param functions // 4/27/05 BMA - GetTarget() identifiers // 4/28/05 ChazM - add fation param constants and IsParameterConstant() // 5/04/05 ChazM - added GetInfluenceVarName() // 5/05/05 BMA - moved GetInfluenceVarName() to ginc_companions.nss // 5/11/05 BMA - fixed bug in GetTarget() // 5/23/05 ChazM - fixed bug in GetObjectTypes() // 9/02/05 BMA-OEI - reorganized functions, added GetSkillConstant() // 10/13/05 FAB - slight change to GetTarget() so that if target = 0, that it defaults to OBJECT_SELF // 12/21/05 ChazM - added StringTrim(), GetTrimmedStringParam() // 1/23/06 BMA-OEI - added TARGET_PC_LEADER, _NEAREST, _SPEAKER // 1/25/06 ChazM - Fixed problem with GetTarget(). // 4/13/06 EPF - GetTarget() checks the owner's tag to make sure he's not the object we're looking for. // 6/16/06 ChazM - added TARGET_OWNED_CHAR for GetTarget() // 7/17/06 ChazM - chaged error text to debug text in GetTarget() // 8/18/06 ChazM - added rNameValueStringPair, GetNameValuePairStruct(), GetNVPValue(), RemoveNVP(), AppendUniqueToNVP() //void main(){} #include "ginc_debug" #include "nw_i0_plot" #include "X0_I0_STRINGLIB" /////////////////////////////////////////////////////////// // Constants & Structs /////////////////////////////////////////////////////////// const string TARGET_KEY = "$"; const string TARGET_OBJECT_SELF = "$OBJECT_SELF"; // OBJECT_SELF const string TARGET_OWNER = "$OWNER"; // OBJECT_SELF (conversation owner) const string TARGET_OWNED_CHAR = "$OWNED_CHAR"; // GetOwnedCharacter const string TARGET_PC = "$PC"; // PCSpeaker const string TARGET_PC_LEADER = "$PC_LEADER"; // FactionLeader (of first PC) const string TARGET_PC_NEAREST = "$PC_NEAREST"; // NearestPC (owned and alive) const string TARGET_PC_SPEAKER = "$PC_SPEAKER"; // PCSpeaker const string TARGET_MODULE = "$MODULE"; const string TARGET_LAST_SPEAKER = "$LASTSPEAKER"; const string PARAM_COMMONER = "$COMMONER"; const string PARAM_DEFENDER = "$DEFENDER"; const string PARAM_HOSTILE = "$HOSTILE"; const string PARAM_MERCHANT = "$MERCHANT"; // Similar to rNameValuePair in x0_i0_stringlib, but with a string value instead of an int. struct rNameValueStringPair { string sName; string sValue; }; /////////////////////////////////////////////////////////// // Prototypes /////////////////////////////////////////////////////////// object GetTarget(string sTarget, string sDefault=TARGET_OWNER); float GetFloatParam(string sString, int nPos); int GetIntParam(string sString, int nPos); string GetStringParam(string sString, int nPos); int IsParameterConstant(string sParameter); int GetObjectTypes(string sType); int GetDurationType(string sType); int GetStandardFaction(string sFactionName); string GetInfluenceVarName(string sTarget); int GetSkillConstant(int nSkill); object GetSoundObjectByTag(string sTarget); struct rNameValueStringPair GetNameValuePairStruct (string sNameValuePair, string sDelimiter = "="); string GetNVPValue(string sNVPList, string sName); string RemoveNVP(string sNVPList, string sName); string AppendUniqueToNVP(string sNVPList, string sName, string sValue, string sDelim="="); /////////////////////////////////////////////////////////// // Function Definitions /////////////////////////////////////////////////////////// // Return constant value for skill n // Used in gc_skill_dc, gc_skill_rank int GetSkillConstant(int nSkill) { int nSkillVal; switch (nSkill) { case 0: // APPRAISE nSkillVal = SKILL_APPRAISE; break; case 1: // BLUFF nSkillVal = SKILL_BLUFF; break; case 2: // CONCENTRATION nSkillVal = SKILL_CONCENTRATION; break; case 3: // CRAFT ALCHEMY nSkillVal = SKILL_CRAFT_ALCHEMY; break; case 4: // CRAFT ARMOR nSkillVal = SKILL_CRAFT_ARMOR; break; case 5: // CRAFT WEAPON nSkillVal = SKILL_CRAFT_WEAPON; break; case 6: // DIPLOMACY nSkillVal = SKILL_DIPLOMACY; break; case 7: // DISABLE DEVICE nSkillVal = SKILL_DISABLE_TRAP; break; case 8: // DISCIPLINE nSkillVal = SKILL_DISCIPLINE; break; case 9: // HEAL nSkillVal = SKILL_HEAL; break; case 10: // HIDE nSkillVal = SKILL_HIDE; break; case 11: // INTIMIDATE nSkillVal = SKILL_INTIMIDATE; break; case 12: // LISTEN nSkillVal = SKILL_LISTEN; break; case 13: // LORE nSkillVal = SKILL_LORE; break; case 14: // MOVE SILENTLY nSkillVal = SKILL_MOVE_SILENTLY; break; case 15: // OPEN LOCK nSkillVal = SKILL_OPEN_LOCK; break; case 16: // PARRY nSkillVal = SKILL_PARRY; break; case 17: // PERFORM nSkillVal = SKILL_PERFORM; break; case 18: // RIDE nSkillVal = SKILL_RIDE; break; case 19: // SEARCH nSkillVal = SKILL_SEARCH; break; case 20: // SET TRAP nSkillVal = SKILL_CRAFT_TRAP; break; case 21: // SLEIGHT OF HAND nSkillVal = SKILL_SLEIGHT_OF_HAND; break; case 22: // SPELLCRAFT nSkillVal = SKILL_SPELLCRAFT; break; case 23: // SPOT nSkillVal = SKILL_SPOT; break; case 24: // SURVIVAL nSkillVal = SKILL_SURVIVAL; break; case 25: // TAUNT nSkillVal = SKILL_TAUNT; break; case 26: // TUMBLE nSkillVal = SKILL_TUMBLE; break; case 27: // USE MAGIC DEVICE nSkillVal = SKILL_USE_MAGIC_DEVICE; break; } return (nSkillVal); } string StringTrim(string sString) { int iLen = GetStringLength(sString); string sLeft = GetStringLeft(sString, 1); while (sLeft == " ") { sString = GetSubString(sString, 1, GetStringLength(sString)-1); sLeft = GetStringLeft(sString, 1); } string sRight = GetStringRight(sString, 1); while (sRight == " ") { sString = GetSubString(sString, 0, GetStringLength(sString)-1); sRight = GetStringRight(sString, 1); } return (sString); } // get specified param from comma delimited string. // return as string string GetTrimmedStringParam(string sString, int nPos) { string sParam = GetTokenByPosition(sString, ",", nPos); return (StringTrim(sParam)); } // get specified param from comma delimited string. // return as string string GetStringParam(string sString, int nPos) { return (GetTokenByPosition(sString, ",", nPos)); } // get specified param from comma delimited string. // return as int int GetIntParam(string sString, int nPos) { return (StringToInt(GetTokenByPosition(sString, ",", nPos))); } // get specified param from comma delimited string. // return as float float GetFloatParam(string sString, int nPos) { return (StringToFloat(GetTokenByPosition(sString, ",", nPos))); } // Return Target by tag or special identifier // Leave sTarget blank to use sDefault override object GetTarget(string sTarget, string sDefault=TARGET_OWNER) { object oTarget = OBJECT_INVALID; // If sTarget is blank, use sDefault if ("" == sTarget || "0" == sTarget) sTarget = sDefault; // Check if sTarget is a special identifier if (IsParameterConstant(sTarget)) { string sIdentifier = sTarget; sIdentifier = GetStringUpperCase(sIdentifier); if (TARGET_OWNER == sIdentifier) oTarget = OBJECT_SELF; else if (TARGET_OBJECT_SELF == sIdentifier) oTarget = OBJECT_SELF; else if (TARGET_OWNED_CHAR == sIdentifier) oTarget = GetOwnedCharacter(OBJECT_SELF); else if (TARGET_PC == sIdentifier) oTarget = GetPCSpeaker(); else if (TARGET_PC_LEADER == sIdentifier) oTarget = GetFactionLeader(GetFirstPC()); else if (TARGET_PC_NEAREST == sIdentifier) oTarget = GetNearestPC(); else if (TARGET_PC_SPEAKER == sIdentifier) oTarget = GetPCSpeaker(); else if (TARGET_MODULE == sIdentifier) oTarget = GetModule(); else if (TARGET_LAST_SPEAKER == sIdentifier) oTarget = GetLastSpeaker(); else { PrettyError("GetTarget() -- " + sIdentifier + " not recognized as special identifier!"); } } else { oTarget = GetNearestObjectByTag(sTarget); // Search area //EPF 4/13/06 -- get nearest misses if the owner is the object we're looking for // so check and see if the target is OBJECT_SELF. I'm putting this after the GetNearest() // call since string compares are expensive, but before the GetObjectByTag() call, since // that's liable to return the wrong instance. We can move this to before the GetNearest() call // if this becomes a problem. if(!GetIsObjectValid(oTarget)) { if(sTarget == GetTag(OBJECT_SELF)) { oTarget = OBJECT_SELF; } } // If not found if (GetIsObjectValid(oTarget) == FALSE) { oTarget = GetObjectByTag(sTarget); // Search module } } // If not found if (GetIsObjectValid(oTarget) == FALSE) { PrettyDebug("GetTarget() -- Could not find target with tag: " + sTarget); } return (oTarget); } // BMA 5/5/05 ginc_companions updated with GetCompInfluenceGlobVar() // get the influence variable name of specified target //string GetInfluenceVarName(string sTarget) //{ // string sVarName; // object oTarg = GetTarget(sTarget, TARGET_OBJECT_SELF); // // if (GetIsObjectValid(oTarg)) // sVarName = GetTag(oTarg); // else // sVarName = sTarget; // // sVarName = sVarName + "_Influence"; // return (sVarName); //} // returns the combined object types of any of the following: // not case sensitive // C = creature // I = item // T = trigger // D = door // A = area of effect // W = waypoint // P = placeable // S = store // E = encounter // ALL = everything int GetObjectTypes(string sType) { sType = GetStringUpperCase(sType); int iObjectType = 0; if (FindSubString(sType, "ALL") != -1) iObjectType = OBJECT_TYPE_ALL; else { iObjectType |= (FindSubString(sType, "C")==-1)?0:OBJECT_TYPE_CREATURE; iObjectType |= (FindSubString(sType, "I")==-1)?0:OBJECT_TYPE_ITEM; iObjectType |= (FindSubString(sType, "T")==-1)?0:OBJECT_TYPE_TRIGGER; iObjectType |= (FindSubString(sType, "D")==-1)?0:OBJECT_TYPE_DOOR; iObjectType |= (FindSubString(sType, "A")==-1)?0:OBJECT_TYPE_AREA_OF_EFFECT; iObjectType |= (FindSubString(sType, "W")==-1)?0:OBJECT_TYPE_WAYPOINT; iObjectType |= (FindSubString(sType, "P")==-1)?0:OBJECT_TYPE_PLACEABLE; iObjectType |= (FindSubString(sType, "S")==-1)?0:OBJECT_TYPE_STORE; iObjectType |= (FindSubString(sType, "E")==-1)?0:OBJECT_TYPE_ENCOUNTER; } return iObjectType; } // return the duration type // not case sensitive // I = INSTANT // P = PERMANENT // T = TEMPORARY int GetDurationType(string sType) { sType = GetStringUpperCase(sType); int iType = DURATION_TYPE_INSTANT; if (FindSubString(sType, "P")) iType = DURATION_TYPE_PERMANENT; if (FindSubString(sType, "T")) iType = DURATION_TYPE_TEMPORARY; return (iType); } // returns the standard faction or -1 if not found int GetStandardFaction(string sFactionName) { int iFaction = -1; if (IsParameterConstant(sFactionName)) { string sTargetFaction = GetStringUpperCase(sFactionName); if (sTargetFaction == PARAM_COMMONER) iFaction = STANDARD_FACTION_COMMONER; else if (sTargetFaction == PARAM_DEFENDER) iFaction = STANDARD_FACTION_DEFENDER; else if (sTargetFaction == PARAM_HOSTILE) iFaction = STANDARD_FACTION_HOSTILE; else if (sTargetFaction == PARAM_MERCHANT) iFaction = STANDARD_FACTION_MERCHANT; } return (iFaction); } // check if this is a parameter constant - starts with TARGET_KEY int IsParameterConstant(string sParameter) { string sKey = GetStringLeft(sParameter, 1); return (TARGET_KEY == sKey); } // returns a sound object object GetSoundObjectByTag(string sTarget) { object oTarget = GetTarget(sTarget); if (GetIsObjectValid(oTarget) == FALSE) ErrorMessage("GetSoundObjetByTag: " + sTarget + " not found!"); else { int iType = GetObjectType(oTarget); if (iType != OBJECT_TYPE_ALL) // sound object don't have their own special type... ErrorMessage("GetSoundObjetByTag: " + sTarget + " is wrong type: " + IntToString(iType) + " - attempting to use anyway."); } return oTarget; } //------------------------------------------------------------- // Name-Value Pair Lists //------------------------------------------------------------- // splits apart a Name-Value Pair string into it's component parts. struct rNameValueStringPair GetNameValuePairStruct (string sNameValuePair, string sDelimiter = "=") { struct rNameValueStringPair oNameValuePair; int iDelimPostion = FindSubString(sNameValuePair, sDelimiter); int iStringLength = GetStringLength(sNameValuePair); oNameValuePair.sName = GetStringLeft(sNameValuePair, iDelimPostion); oNameValuePair.sValue = GetStringRight(sNameValuePair, iStringLength - iDelimPostion - GetStringLength(sDelimiter)); return (oNameValuePair); } // return Value string for name/value pair, empty string if not found. string GetNVPValue(string sNVPList, string sName) { struct rNameValueStringPair oNameValuePair; int bFound = FALSE; int i = 0; string sRet = ""; string sNameValuePair = GetStringParam(sNVPList, i); while (sNameValuePair != "" && !bFound) { oNameValuePair = GetNameValuePairStruct(sNameValuePair); if (oNameValuePair.sName == sName) { bFound = TRUE; sRet = oNameValuePair.sValue; break; } i++; sNameValuePair = GetStringParam(sNVPList, i); } return sRet; } // Remove Name-Value pair from Name-Value pair list string RemoveNVP(string sNVPList, string sName) { string sValue = GetNVPValue(sNVPList, sName); string sNameValuePair = sName + "=" + sValue; sNVPList = RemoveListElement(sNVPList, sNameValuePair); return(sNVPList); } // Set a Name-Value pair in a list of Name-Value Pairs string AppendUniqueToNVP(string sNVPList, string sName, string sValue, string sDelim="=") { string sNameValuePair = sName + sDelim + sValue; // Remove old value if it exists. sName = RemoveNVP(sNVPList, sName); // append new value sNVPList = AppendToList(sNVPList, sNameValuePair); return (sNVPList); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ginc_roster.nss //:: //:: Various Roster List management functions //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: BMA-OEI //:: Created on: 10/18/05 //:: //:://///////////////////////////////////////////////////////////////////////// #include "ginc_debug" //------------------------------------------------- // Function Prototypes //------------------------------------------------- void PrintRosterList(); void AddCompanionsToRosterList(); void ClearRosterList(); void TestAddRosterMemberByTemplate(string sRosterName, string sTemplate); void TestRemoveRosterMember(string sRosterName); //------------------------------------------------- // Function Definitions //------------------------------------------------- // List roster member names on screen void PrintRosterList() { int nCount = 0; string sRosterName = GetFirstRosterMember(); PrettyMessage("Printing Roster List..."); while (sRosterName != "") { nCount = nCount + 1; PrettyMessage(" Member " + IntToString(nCount) + ": " + sRosterName); sRosterName = GetNextRosterMember(); } PrettyMessage("Roster List finished (" + IntToString(nCount) + " members)."); } // Add all campaign companions to roster void AddCompanionsToRosterList() { TestAddRosterMemberByTemplate("ammon_jerro", "co_ammon_jerro"); TestAddRosterMemberByTemplate("bishop", "co_bishop"); TestAddRosterMemberByTemplate("casavir", "co_casavir"); TestAddRosterMemberByTemplate("construct", "co_construct"); TestAddRosterMemberByTemplate("elanee", "co_elanee"); TestAddRosterMemberByTemplate("grobnar", "co_grobnar"); TestAddRosterMemberByTemplate("khelgar", "co_khelgar"); TestAddRosterMemberByTemplate("neeshka", "co_neeshka"); TestAddRosterMemberByTemplate("qara", "co_qara"); TestAddRosterMemberByTemplate("sand", "co_sand"); TestAddRosterMemberByTemplate("shandra", "co_shandra"); TestAddRosterMemberByTemplate("zhjaeve", "co_zhjaeve"); } // Remove all members from roster void ClearRosterList() { int nCount = 0; int bSuccess = 0; string sMember = GetFirstRosterMember(); while (sMember != "") { nCount++; bSuccess = RemoveRosterMember(sMember); if (bSuccess == TRUE) { PrettyMessage("ginc_roster: ClearRosterList() successfully removed " + sMember); } else { PrettyError("ginc_roster: ClearRosterList() could not find " + sMember); } sMember = GetFirstRosterMember(); } } // Attempt AddRosterMemberByTemplate() void TestAddRosterMemberByTemplate(string sRosterName, string sTemplate) { int bResult = AddRosterMemberByTemplate(sRosterName, sTemplate); if (bResult == TRUE) { PrettyMessage("ginc_roster: successfully added " + sRosterName + " (" + sTemplate + ")"); } else { PrettyError( "ginc_roster: failed to add " + sRosterName + " (" + sTemplate + ")"); } } // Attempt RemoveRosterMember() void TestRemoveRosterMember(string sMember) { int bResult = RemoveRosterMember(sMember); if (bResult == TRUE) { PrettyMessage("ginc_roster: successfully removed " + sMember); } else { PrettyError("ginc_error: failed to remove " + sMember); } } //void main(){} // ginc_sound /* Sound and Music functions. */ // EPF 8/23/06 // some variables used in the ga_music functions to save and load tracks const string MUSIC_TRACK_DAY = "00_sDayMusic"; const string MUSIC_TRACK_NIGHT = "00_sNightMusic"; const string MUSIC_TRACK_BATTLE = "00_sBattleMusic"; void SaveMusicTrack(object oArea); void SaveBattleMusicTrack(object oArea); void RestoreMusicTrack(object oArea); void ChangeMusicTrack(object oArea, int nTrack); void RestoreBattleMusicTrack(object oArea); //-------------------------------------- // Music Related //-------------------------------------- void SaveMusicTrack(object oArea) { SetLocalInt(oArea,MUSIC_TRACK_DAY, MusicBackgroundGetDayTrack(oArea)); SetLocalInt(oArea,MUSIC_TRACK_NIGHT, MusicBackgroundGetNightTrack(oArea)); } void SaveBattleMusicTrack(object oArea) { SetLocalInt(oArea,MUSIC_TRACK_BATTLE, MusicBackgroundGetBattleTrack(oArea)); } void RestoreMusicTrack(object oArea) { MusicBackgroundChangeDay(oArea, GetLocalInt(oArea,MUSIC_TRACK_DAY)); MusicBackgroundChangeNight(oArea, GetLocalInt(oArea,MUSIC_TRACK_NIGHT)); } void ChangeMusicTrack(object oArea, int nTrack) { MusicBackgroundChangeDay(oArea, nTrack); MusicBackgroundChangeNight(oArea, nTrack); } void RestoreBattleMusicTrack(object oArea) { MusicBattleChange(oArea, GetLocalInt(oArea,MUSIC_TRACK_BATTLE)); } //:://///////////////////////////////////////////////////////////////////////// //:: //:: ginc_transition //:: //:: Global include for transitions. //:: //:://///////////////////////////////////////////////////////////////////////// // DBR 3/2/06 // ChazM 3/3/06 - parameterized GatherPartyTransition(), added IsPartyGathered() // DBR 4/9/6 - Changed to message box for "Gather party" // BMA-OEI 5/01/06 - Changed IsPartyGathered() to check all party members // BMA-OEI 6/14/06 - Added SinglePartyTransition() // ChazM 6/22/06 - Temporarily set gather radius really large. // BMA-OEI 6/24/06 - Moved nw_g0_transition code into AttemptAreaTransition() // BMA-OEI 7/04/06 - Check to Remove Dominated On Transition //void main(){} #include "ginc_effect" #include "x2_inc_switches" const float fGATHER_RADIUS = 200.0f; const string VAR_GLOBAL_GATHER_PARTY = "bGATHER_PARTY_TRAN"; void AttemptAreaTransition( object oObject, object oDestination ); void ReportPartyGather( object oPCF ); int IsPartyGathered( object oPC ); void GatherPartyTransition( object oPC, object oTransitionTarget ); void SinglePartyTransition( object oPC, object oDestination ); // Standard NWN2 area transition code void AttemptAreaTransition( object oObject, object oDestination ) { // BMA-OEI 7/04/06 - Check if in group and using group campaign flag if ( GetGlobalInt(CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION) == TRUE ) { if ( ( GetIsPC(oObject) == TRUE ) || ( GetFactionEqual(oObject, GetFirstPC()) == TRUE ) ) { int nRemoved = 0; object oFM = GetFirstFactionMember( oObject, FALSE ); while ( GetIsObjectValid(oFM) == TRUE ) { nRemoved = nRemoved + RemoveEffectsByType( oFM, EFFECT_TYPE_DOMINATED ); oFM = GetNextFactionMember( oObject, FALSE ); } if ( nRemoved > 0 ) { // Abort transition if domianted effect was found and removed return; } } } // k_mod_load.nss campaign setting - override "Gather Party" transition // TODO: What if oClicker is NPC? if ( GetGlobalInt( VAR_GLOBAL_GATHER_PARTY ) == 1 ) { GatherPartyTransition( oObject, oDestination ); return; } if ( GetIsPartyTransition( OBJECT_SELF ) == TRUE ) { SinglePartyTransition( oObject, oDestination ); } else { AssignCommand( oObject, JumpToObject( oDestination ) ); } } // Complain that party needs to be gathered! void ReportPartyGather(object oPCF) { CloseGUIScreen(oPCF, "SCREEN_MESSAGEBOX_DEFAULT"); DelayCommand( 0.1, DisplayMessageBox( oPCF, // Display a message box for this PC 161846, // string ref to display "", // Message to display "", // Callback for clicking the OK button "", // Callback for clicking the Cancel button FALSE, // display the Cancel button "SCREEN_MESSAGEBOX_DEFAULT", // Display the tutorial message box -1, // OK string ref "", // OK string -1, // Cancel string ref "" // Cancel string ) ); } // Check if party is gathered ( alive, not in conversation, and nearby ) int IsPartyGathered( object oPC ) { object oArea = GetArea( oPC ); object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oFM ) == TRUE ) { // For all members in the area if ( GetArea( oFM ) == oArea ) { if ( ( GetIsDead( oFM ) == TRUE ) || ( IsInConversation( oFM ) == TRUE ) || ( GetDistanceBetween( oFM, oPC ) >= fGATHER_RADIUS ) ) { return ( FALSE ); } } oFM = GetNextFactionMember( oPC, FALSE ); } return ( TRUE ); } // Transition to oTransitionTarget if oPC's party is gathered ( alive, not in conversation, and nearby ) // Otherwise, ask oPC to first gather the party. void GatherPartyTransition( object oPC, object oTransitionTarget ) { if ( ( GetIsPC( oPC ) == FALSE ) || ( GetIsDead( oPC ) == TRUE ) || ( IsInConversation( oPC ) == TRUE ) ) { return; } if ( IsPartyGathered( oPC ) == FALSE ) { ReportPartyGather( oPC ); return; } SinglePartyTransition( oPC, oTransitionTarget ); } // Forces oPC's faction to be alive and commandable before sending // them to oDestination via JumpPartyToArea(). void SinglePartyTransition( object oPC, object oDestination ) { effect eRes = EffectResurrection(); // For each party member, revive and set commandable object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid( oFM ) == TRUE ) { SetCommandable( TRUE ); ApplyEffectToObject( DURATION_TYPE_INSTANT, eRes, oFM ); oFM = GetNextFactionMember( oPC, FALSE ); } // Transition and trigger FiredFromPartyTransition() JumpPartyToArea( oPC, oDestination ); } // ginc_trigger /* trigger related functions */ // ChazM 4/6/05 // ChazM 4/19/05 - added -1 Run option // ChazM 5/3/05 - added Jump option, TalkNow, and CutsceneBars // ChazM 5/6/05 - fixed TalkNow to start convo before running to player // ChazM 5/25/05 - added OnceOnly // EPF 6/3/05 - Making the entering object the target of the GetNearestObjectByTag() call, which is more reliable than having the // trigger own the function. // ChazM 6/14/05 - Fixed problem with target not being found. // ChazM 6/14/05 - Blank for NPC_Tag now refers to the entering PC. // ChazM 6/25/05 - Split functions from gtr_speak_node into this include // ChazM 7/13/05 - Added bunch of PrintString()'s // ChazM 7/13/05 - Modified StandardSpeakTriggerConditions() to support MultiUse // EPF 7/29/05 - Speak trigger will now fire even if a player is in combat. // ChazM 9/12/05 - Modified GetTriggerTarget() // EPF 9/24/95 - found a second instance of a check that aborts the speak trigger if the player was in combat. Commented it out. // BMA-OEI 1/6/06 - changed default GetTriggerTarget() to OBJECT_SELF // BMA-OEI 1/13/06 - added GetTriggerTarget() warning, triggers as owners mess up random cams // BMA-OEI 2/7/06 - Added comments/debug lines to GetTriggerTarget(), DoSpeakTrigger() // EPF 2/10/06 - fixed compiler error in line 146. // BMA-OEI 2/28/06 - added PrepareForConversation() // BMA-OEI 3/6/06 - added CombatCutsceneSetup, updated StandardSpeakTriggerConditions() for any PC party member // BMA-OEI 3/7/06 - modified CombatCutsceneCleanUp to use IPoint Cleaner // BMA-OEI 3/21/06 - TODO: GetIsCompanionPossessionBlocked() check // DBR 6/16/06 - Put in check for PC faction members in same area already in a MP cutscene. Also with BMA put in cases for all kinds of un-possessed companions setting off the trigger. #include "ginc_cutscene" #include "ginc_misc" //#include "x2_inc_switches" // ***** PROTOTYPES ***** // Return Target by tag or special identifier. Leave sTarget blank to use entering object. object GetTriggerTarget(string sTarget, object oTriggeringObject); // Check standard speak trigger conditions for entering object int StandardSpeakTriggerConditions(object oEnter); /* Starts a conversation based on variables set on trigger. The following variables will be examined on the trigger. First 2 paramaters are required. Order is not important NPC_Tag - Tag of creature to make comment. Must be in this area. Blank defaults to the entering PC. Conversation - Conversation file to play. Node - Node of the conversation to speak. Node indexes are set using gc_node() in the dialog conditionals. Do not define a node 0, as this is reserved. Run - Set to following: 2 - Target Jumps to PC 1 - Target runs to PC 0 - (default) Target Walks to PC -1 - Target Stays Put (and TalkNow=1 by default) TalkNow - Set to following: 0 - (default) use default based on Run mode. 1 - talk immediately, regardless of distance 2 - only talk when close (default except when Run = -1) CutsceneBars - Set to following: 0 - (default) no cutscene bars 1 - show cutscene bars OnceOnly - Controls whether or not NPC's Node index is cleared after it's first use. Set to following: 0 - (default) the node index is not reset by gc_node 1 - gc_node will reset the node index to 0 so that it only recognizes it once MultiUse - Controls whether the Speak Trigger fires only once or on every enter 0 - (default) Only triggers once 1 - Triggers every time. CombatCutsceneSetup - Controls whether to Plot party, Hide hostiles, hold AI for duration of conversation. 0 - (default) Normal speak trigger 1 - Use CombatCutsceneSetup() and QueueCombatCutsceneCleanUp() */ void DoSpeakTrigger(object oEnter); // ***** DEFINITIONS ***** // Return Speaker Target by tag or special identifier. Leave sTarget blank to use triggering object. object GetTriggerTarget(string sTarget, object oTriggeringObject) { object oTarget = OBJECT_INVALID; if (sTarget == "") { oTarget = oTriggeringObject; } else { oTarget = GetNearestObjectByTag(sTarget, oTriggeringObject); if (GetIsObjectValid(oTarget) == FALSE) { oTarget = GetNearestObjectByTag(sTarget); } } if (GetIsObjectValid(oTarget) == FALSE) { PrettyDebug("GetTriggerTarget: ERROR - NPC target: " + sTarget + " was not found!"); } return (oTarget); } // Standard SpeakTrigger should fire only if oEnter is in the PC party int StandardSpeakTriggerConditions(object oEnter) { // Check if oEnter is in the PC's faction if ( GetIsPC( oEnter ) == FALSE ) { PrettyDebug( "SpeakTrigger: " + GetName(oEnter) + " is not a PC." ); object oPC = GetFirstPC(); if ( GetFactionEqual( oEnter, oPC ) == FALSE ) { PrettyDebug( "SpeakTrigger: " + GetName(oEnter) + " is not in " + GetName(oPC) + "'s party." ); return ( FALSE ); } } // Check if SpeakTrigger can fire more than once int bMultiUse = GetLocalInt(OBJECT_SELF, "MultiUse"); if ((bMultiUse == FALSE) && IsMarkedAsDone()) { PrettyDebug( "SpeakTrigger: cannot fire more than once" ); return (FALSE); } // EPF 7/29/05 -- after modifying DetermineCombatRound(), it should be okay to fire a speak trigger, even when in combat. // if (GetIsInCombat(oPC)) // return FALSE; /* This is prone to error by typing scripts as var values and removed for now: // ConditionScript - Condition script to run on entering PC to see if speak trigger should fire. // use SetExecutedScriptReturnValue() with TRUE or FALSE to check conditions // use stc_template as a template for the speak trigger conditions string sConditionScript = GetLocalString(OBJECT_SELF, "ConditionScript"); if (sConditionScript != "") if (!ExecuteScriptAndReturnInt(sConditionScript, oPC)) return FALSE; */ //DBR 6/16/06 - Check to make sure no one in this area is in a MP conversation object oPCF = GetFirstFactionMember(oEnter,FALSE); while (GetIsObjectValid(oPCF)) { if ((IsInMultiplayerConversation(oPCF))&&(GetArea(oEnter)==GetArea(oPCF))) //MP conversation going on in this area { DelayCommand( 0.1f, PrettyError( "SpeakTrigger: " + GetName(oPCF) + " is already in a MP cutscene." ) ); return FALSE; } oPCF = GetNextFactionMember(oEnter,FALSE); } PrettyDebug( "SpeakTrigger: " + GetName(oEnter) + " passed the StandardSpeakTriggerConditions!" ); return (TRUE); } void DoSpeakTrigger(object oEnter) { string sNPCTag = GetLocalString(OBJECT_SELF, "NPC_Tag"); string sConversation = GetLocalString(OBJECT_SELF, "Conversation"); int iNodeIndex = GetLocalInt(OBJECT_SELF, "Node"); int nRun = GetLocalInt(OBJECT_SELF, "Run"); // Don't use 0 as user input for this since that is default if not there. int nTalkNow = GetLocalInt(OBJECT_SELF, "TalkNow"); int bCutsceneBars = GetLocalInt(OBJECT_SELF, "CutsceneBars"); int bOnceOnly = GetLocalInt(OBJECT_SELF, "OnceOnly"); int bCombatCutsceneSetup = GetLocalInt(OBJECT_SELF, "CombatCutsceneSetup"); // Default values of ActionStartConversation() int bPrivateConversation = FALSE; int bPlayHello = TRUE; int bIgnoreStartDistance = FALSE; int bDisableCutsceneBars = TRUE; bDisableCutsceneBars = !bCutsceneBars; // Find conversation Speaker // BMA-OEI 3/21/06 should we verify this in StandardSpeakTriggerConditions? object oTarg = GetTriggerTarget(sNPCTag, oEnter); if (GetIsObjectValid(oTarg) == FALSE) { PrettyDebug("DoSpeakTrigger: ERROR - Target speaker is invalid!"); return; } if (GetIsPC(oTarg) == TRUE) { PrettyDebug("DoSpeakTrigger: WARNING - SPEAKER: " + GetName(oTarg) + " is controlled by a PC!"); } // DetermineCombatRound() modified so hopefully it should be okay to converse even while in combat. // EPF 9/24/05 // if (GetIsInCombat(oTarg)) // { // return; // } // Store info on target object SetLocalInt(oTarg, "sn_NodeIndex", iNodeIndex ); SetLocalInt(oTarg, "sn_OnceOnly", bOnceOnly ); // If CombatCutsceneSetup is required if (bCombatCutsceneSetup == 1) { CombatCutsceneSetup(oEnter); } // Revive and remove negative effects on PC party and oTarg MakeConversable(oEnter, TRUE); MakeConversable(oTarg, FALSE); ClearPartyActions(oEnter, TRUE); //DBR 6/16/06 if (GetIsOwnedByPlayer(oEnter) && (!GetIsPC(oEnter))) //oEnter is A "created" character not being possessed by anyone. { oEnter = SetOwnersControlledCompanion(GetControlledCharacter(oEnter),oEnter); //Warp the PC into his created character and return } else if (GetIsCompanionPossessionBlocked(oEnter)&&(!GetIsPC(oEnter))&&(!GetIsOwnedByPlayer(oEnter))) // oEnter is a companion who is not being controlled, and is blocked from possession { if (GetCanTalkToNonPlayerOwnedCreatures(oTarg)) //Target can talk to anyone, so whoever the faction leader is A-O-K to talk to this guy { object oLeader = GetFactionLeader(oEnter); AssignCommand(oLeader, ClearAllActions(TRUE)); AssignCommand(oLeader, JumpToObject(oEnter)); oEnter = oLeader; } else //Picky NPC, force possession of an owned character and use them (since it is companion only in this case, any PC will do { object oLeader = GetFactionLeader(oEnter); object oOwned = SetOwnersControlledCompanion(oLeader,GetOwnedCharacter(oLeader)); //Warp the PC into his created character and return AssignCommand(oOwned, ClearAllActions(TRUE)); AssignCommand(oOwned, JumpToObject(oEnter)); oEnter = oOwned; } } else if (!GetIsCompanionPossessionBlocked(oEnter)&&(!GetIsPC(oEnter))&&(!GetIsOwnedByPlayer(oEnter))) // oEnter is a companion who is not being controlled, but can be { oEnter = SetOwnersControlledCompanion(GetFactionLeader(oEnter),oEnter); //Force possession of Faction Leader into Companion } //All other cases involve oEnter being a PC or companion who is CURRENTLY being possessed by a player. They are fine to pass in, and engine will handle a swap if need be. // If oEnter is still not controlled by a player if (GetIsPC(oEnter) == FALSE) { object oLeader = GetFactionLeader(oEnter); AssignCommand(oLeader, ClearAllActions(TRUE)); AssignCommand(oLeader, JumpToObject(oEnter)); oEnter = oLeader; } AssignCommand(oTarg, ClearAllActions(TRUE)); // If oTarg shouldn't move, start conversation immediately if (nRun == -1) { nTalkNow = 1; } bIgnoreStartDistance = TRUE; if (nTalkNow == 1) { AssignCommand(oTarg, ActionStartConversation(oEnter, sConversation, bPrivateConversation, bPlayHello, bIgnoreStartDistance, bDisableCutsceneBars)); } else { PrettyDebug("DoSpeakTrigger: WARNING - TalkNow = 0, PC may not be ready for conversation!"); // If oTarg is too far from the PC if (GetDistanceBetween(oEnter, oTarg) >= 3.0f) { bIgnoreStartDistance = FALSE; switch (nRun) { case -1: // Don't move break; case 0: // Walk AssignCommand(oTarg, ActionForceMoveToObject(oEnter, FALSE, 2.0f)); break; case 1: // Run AssignCommand(oTarg, ActionForceMoveToObject(oEnter, TRUE, 2.0f)); break; case 2: // Jump AssignCommand(oTarg, JumpToObject(oEnter)); break; } } AssignCommand(oTarg, ActionStartConversation(oEnter, sConversation, bPrivateConversation, bPlayHello, bIgnoreStartDistance, bDisableCutsceneBars)); } // If CombatCutsceneSetup is required //if (bCombatCutsceneSetup == 1) //{ // object oIPCleaner = CreateObject(OBJECT_TYPE_PLACEABLE, IPC_RESREF, GetLocation(oEnter)); // AssignCommand(oIPCleaner, QueueCombatCutsceneCleanUp()); //} MarkAsDone(); } // ginc_utility.nss /* This is the main utility script for NWN2 */ // FAB 10/12/04 // ChazM 3/8/05 - file name changed // BMA-OEI 8/03/05 - error checking if waypoint not valid, rewrote for legibility // BMA-OEI 8/04/05 - added UT_FakeEncounter() // BMA-OEI 8/28/05 - added UT_SpawnAtWP() // ************** // SCRIPT DEFINES // ************** // This function spawns resref sTemplate at each waypoint sWaypoint in the module. void UT_FakeEncounter(string sTemplate, string sWaypoint, int bUseAppearAnimation = FALSE); // This function spawns someone with resref sObject at waypoint "sp_". // This command can be delayed and the object can be given a new tag after being spawned. // If a delay isn't necessary then use GN_Spawn. void UT_SpawnDelay(string sObject, int nInstance = 0, float fDelay = 0.0, string sNewTag = ""); // This function spawns someone with resref sObject at waypoint "sp_". // It can be given a new tag after it is spawned. The function returns the object ID of what was created. // If a delay is necessary then use GN_SpawnDaly (but you won't be able to get the object ID from that function). object UT_Spawn(string sObject, int nInstance = 0, string sNewTag = ""); object UT_SpawnAtWP(string sTemplate, string sWaypoint, string sNewTag = "", int bUseAppearAnimation = FALSE); // *********************************** // PRIVATE FUNCTIONS - don't use these // *********************************** object UT_CreateObjectAtLocation(string sObject, location lLoc, string sNewTag, int bUseAppearAnimation = FALSE) { object oCreature; if (sNewTag == "") { oCreature = CreateObject(OBJECT_TYPE_CREATURE, sObject, lLoc); } else { oCreature = CreateObject(OBJECT_TYPE_CREATURE, sObject, lLoc, FALSE, sNewTag); } return oCreature; } void UT_CreateObjectAtLocVoid(string sObject, location lLoc, string sNewTag, int bUseAppearAnimation = FALSE) { UT_CreateObjectAtLocation(sObject, lLoc, sNewTag, bUseAppearAnimation); } // ************** // MAIN FUNCTIONS // ************** void UT_FakeEncounter(string sTemplate, string sWaypoint, int bUseAppearAnimation = FALSE) { object oWP; int nCount = 0; location lLoc; oWP = GetObjectByTag(sWaypoint, nCount); while (GetIsObjectValid(oWP) == TRUE) { lLoc = GetLocation(oWP); UT_CreateObjectAtLocVoid(sTemplate, lLoc, "", bUseAppearAnimation); nCount = nCount + 1; oWP = GetObjectByTag(sWaypoint, nCount); } PrintString("ginc_utility: UT_FakeEncounter() spawned " + IntToString(nCount) + " " + sTemplate); } void UT_SpawnDelay(string sTemplate, int nInstance = 0, float fDelay = 0.0, string sNewTag = "") { object oWP; location lLoc; if (nInstance != 0) { oWP = GetWaypointByTag("sp_" + sTemplate + IntToString(nInstance)); } else { oWP = GetWaypointByTag("sp_" + sTemplate); } if (GetIsObjectValid(oWP) == TRUE) { lLoc = GetLocation(oWP); DelayCommand(fDelay, UT_CreateObjectAtLocVoid(sTemplate, lLoc, sNewTag)); } else { PrintString("ginc_utility: UT_SpawnDelay() invalid waypoint"); } } object UT_Spawn(string sTemplate, int nInstance = 0, string sNewTag = "") { object oCreature; object oWP; location lLoc; if (nInstance != 0) { oWP = GetWaypointByTag("sp_" + sTemplate + IntToString(nInstance)); } else { oWP = GetWaypointByTag("sp_" + sTemplate); } if (GetIsObjectValid(oWP) == TRUE) { lLoc = GetLocation(oWP); oCreature = UT_CreateObjectAtLocation(sTemplate, lLoc, sNewTag); } else { PrintString("ginc_utility: UT_Spawn() invalid waypoint"); } return oCreature; } object UT_SpawnAtWP(string sTemplate, string sWaypoint, string sNewTag = "", int bUseAppearAnimation = FALSE) { object oCreature; object oWP = GetObjectByTag(sWaypoint); location lWP = GetLocation(oWP); oCreature = UT_CreateObjectAtLocation(sTemplate, lWP, sNewTag, bUseAppearAnimation); return oCreature; } // TEST MAIN - uncomment to debug the include file /*void main() { }*/ // ginc_var_ops // // include file for common functionality with g*_global_* and g*_local_* scripts // ChazM 4/12/05 (mod) // ChazM 5/4/05 added CalcNewIntValue() // ChazM 6/15/05 modified CompareInts() to be able to reference a companion's influence // BMA-OEI 1/13/06 modified CheckVariableFloat for EPSILON check // ChazM 8/24/06 CompareInts() no longer able to reference a companion's influence to remove dependency on kinc_companion #include "ginc_companion" #include "ginc_math" // Prototypes int CheckVariableFloat(float fValue, string sOperator, float fCheck); int CheckVariableInt(int nValue, string sOperator, int nCheck); int CompareInts(int nValue, string sCheck); int CalcNewIntValue(int nOldValue, string sChange, int bDefaultIsDelta = FALSE); // CheckVariableFloat() // // Evaluates the expression [fValue] [sOperator] [fCheck], as in, say, 5 < 3 // and returns the result -- true or false // sOperator is =, >, <, or ! (for not equals) int CheckVariableFloat(float fValue, string sOperator, float fCheck) { //GREATER THAN if ( sOperator == ">") { return (fValue > fCheck); } //LESS THAN if ( sOperator == "<") { return (fValue < fCheck); } //NOT EQUAL TO if ( sOperator == "!") { //return (fValue != fCheck); fValue = fabs(fValue - fCheck); return (fValue > EPSILON); } //EQUAL TO if( sOperator == "=") { //return (fValue == fCheck); fValue = fabs(fValue - fCheck); return (fValue < EPSILON); } return FALSE; } // CheckVariableInt() // // Evaluates the expression [nValue] [sOperator] [nCheck], as in, say, 5 < 3 // and returns the result -- true or false // sOperator is =, >, <, or ! (for not equals) int CheckVariableInt(int nValue, string sOperator, int nCheck) { //GREATER THAN if ( sOperator == ">") { return (nValue > nCheck); } //LESS THAN if ( sOperator == "<") { return (nValue < nCheck); } //NOT EQUAL TO if ( sOperator == "!") { return (nValue != nCheck); } //EQUAL TO if( sOperator == "=") { return (nValue == nCheck); } return FALSE; } // compare integer values // nValue - value to compare // sCheck - string containing optional comparison operator and value int CompareInts(int nValue, string sCheck) { int nCheck; string sValue; string sOperator = GetStringLeft(sCheck, 1); //first we consider cases where the user specified an operator as the first character //of sCheck if(sOperator == ">" || sOperator == "<" || sOperator == "=" || sOperator == "!") { sValue = GetStringRight( sCheck,GetStringLength(sCheck)-1 ); } //default case -- no operator specified so use whole string as our check value else { sValue = sCheck; sOperator = "="; } // sValue is now sCheck minus any operator on the front end // check if sValue has a tag // string sValueTag = GetStringLeft(sValue, 1); // // if(sValueTag == "C" || sValueTag == "c") // { // int nCompanion = StringToInt(GetStringRight( sValue,GetStringLength(sValue)-1 )); // nCheck = GetGlobalInt(GetCompInfluenceGlobVar(nCompanion)); // } // else // { nCheck = StringToInt(sValue); // } return (CheckVariableInt(nValue, sOperator, nCheck)); } struct ChangeComponents { string sOperator; string sValue; }; // returns the operator and value from sChange. // bDefaultIsDelta affect whether operator is "+" or "=" when an operator is not provided struct ChangeComponents GetChangeComponents(string sChange, int bDefaultIsDelta) { struct ChangeComponents xChange; // return value string sOperator = GetStringLeft(sChange, 1); if ((sOperator == "=") || (sOperator == "+") || (sOperator == "-")) { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); // handle ++, --, +, - string sChar2 = GetStringLeft(sChange, 1); if ((sChar2 == "+") || (sChar2 == "-") || (sChar2 == "")) sChange = "1"; } else { // doesn't start with operator if (bDefaultIsDelta) sOperator = "+"; else sOperator = "="; } xChange.sOperator = sOperator; xChange.sValue = sChange; return (xChange); } // applies sChange to nOldValue and returns the new value. // nOldValue - previous value // sChange - change string such as "5", "-2", "=3", etc. // bDefaultIsDelta - TRUE = treat integer as Delta, FALSE = treat integer as value to set. int CalcNewIntValue(int nOldValue, string sChange, int bDefaultIsDelta = FALSE) { struct ChangeComponents xChange = GetChangeComponents(sChange, bDefaultIsDelta); int nValue = StringToInt(xChange.sValue); int nNewValue; if (xChange.sOperator == "+") nNewValue = nOldValue + nValue; else if (xChange.sOperator == "-") nNewValue = nOldValue - nValue; else { // if not + or - then just set the value nNewValue = nValue; } return(nNewValue); } /* // applies sChange to nOldValue and returns the new value. // nOldValue - previous value // sChange - change string such as "5", "-2", "=3", etc. // bDefaultIsDelta - TRUE = treat integer as Delta, FALSE = treat integer as value to set. int OldCalcNewIntValue(int nOldValue, string sChange, int bDefaultIsDelta) { int nChange; if (GetStringLeft(sChange, 1) == "=") { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); nChange = StringToInt(sChange); } else if (GetStringLeft(sChange, 1) == "+") { // If sChange is just "+" then default to increment by 1 if (GetStringLength(sChange) == 1) { nChange = nOldValue + 1; } else // This means there's more than just "+" { if (GetSubString(sChange, 1, 1) == "+") // "++" condition { nChange = nOldValue + 1; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); nChange = nOldValue + StringToInt(sChange); } } } else if (GetStringLeft(sChange, 1) == "-") { // If sChange is just "-" then default to increment by 1 if (GetStringLength(sChange) == 1) { nChange = nOldValue - 1; } else // This means there's more than just "-" { if (GetSubString(sChange, 1, 1) == "-") // "--" condition { nChange = nOldValue - 1; } else { sChange = GetStringRight(sChange, GetStringLength(sChange) - 1); nChange = nOldValue - StringToInt(sChange); } } } else { if (sChange == "") nChange = nOldValue + 1; if (bDefaultIsDelta) { nChange = nOldValue + StringToInt(sChange); } else { nChange = StringToInt(sChange); } } return(nChange); } */ // ginc_vars /* Global/local variable related functions */ // ChazM 9/22/05 // ChazM 10/01/05 added IsMarkedAsDone(), MarkAsDone(), IsMarkedAsDoneForInt(), MarkAsDoneForInt() // ChazM 1/31/06 added GetGlobalArrayString(), SetGlobalArrayString(), GetGlobalArrayInt(), SetGlobalArrayInt() // ChazM 9/11/06 added GetDoneFlag(); added params to IsMarkedAsDone(), MarkAsDone(); removed IsMarkedAsDoneForInt(), MarkAsDoneForInt() // ChazM 9/11/06 added error messages for IsMarkedAsDone(), MarkAsDone() // ChazM 9/12/06 added DoneFlagSanityCheck(); removed commented code //void main() {} #include "ginc_debug" const string DONE_ONCE = "DoneOnce"; //------------------------------------------------- // Function Prototypes //------------------------------------------------- float GetGlobalIntAsFloat(string sVarName); int ModifyGlobalInt(string sVarName, int iDelta); int ModifyLocalInt(object oObject, string sVarName, int iDelta); void ModifyLocalIntOnFaction(object oPC, string sVarName, int iDelta, int bPCOnly=TRUE); object GetGlobalObject(string sVarName); void SetGlobalObject(string sVarName, object oObj); void DeleteGlobalObject(string sVarName); string GetDoneFlag(int iFlag=0); void DoneFlagSanityCheck(object oObject); int IsMarkedAsDone(object oObject=OBJECT_SELF, int iFlag=0); void MarkAsDone(object oObject=OBJECT_SELF, int iFlag=0); string GetGlobalArrayString(string sVarName, int nVarNum); void SetGlobalArrayString(string sVarName, int nVarNum, string nValue); int GetGlobalArrayInt(string sVarName, int nVarNum); void SetGlobalArrayInt(string sVarName, int nVarNum, int nValue); //------------------------------------------------- // Function Definitions //------------------------------------------------- // return int as float float GetGlobalIntAsFloat(string sVarName) { return (IntToFloat(GetGlobalInt(sVarName))); } // Change value of Global Int by iDelta amount int ModifyGlobalInt(string sVarName, int iDelta) { int iNewVal = GetGlobalInt(sVarName) + iDelta; SetGlobalInt(sVarName, iNewVal); return (iNewVal); } // Change value of Local Int by iDelta amount int ModifyLocalInt(object oObject, string sVarName, int iDelta) { int iNewVal = GetLocalInt(oObject, sVarName) + iDelta; SetLocalInt(oObject, sVarName, iNewVal); return (iNewVal); } void ModifyLocalIntOnFaction(object oPC, string sVarName, int iDelta, int bPCOnly=TRUE) { object oPartyMem = GetFirstFactionMember(oPC, bPCOnly); while (GetIsObjectValid(oPartyMem)) { ModifyLocalInt(oPartyMem, sVarName, iDelta); oPartyMem = GetNextFactionMember(oPC, bPCOnly); } } // hopefully these 3 funcs will be implemented as functions in NWScript object GetGlobalObject(string sVarName) { object oMod = GetModule(); return GetLocalObject(oMod, sVarName); } void SetGlobalObject(string sVarName, object oObj) { object oMod = GetModule(); SetLocalObject(oMod, sVarName, oObj); } void DeleteGlobalObject(string sVarName) { object oMod = GetModule(); DeleteLocalObject(oMod, sVarName); } string GetDoneFlag(int iFlag=0) { return(DONE_ONCE + (iFlag==0?"":IntToString(iFlag))); } void DoneFlagSanityCheck(object oObject) { int iObjType = GetObjectType(oObject); if (iObjType == OBJECT_TYPE_ITEM) PrettyError("MarkAsDone()/IsMarkedAsDone() should not be used with items - Use MarkItemAsDone()/IsItemMarkedAsDone(). Name of item passed =" + GetName(oObject)); if (iObjType == OBJECT_TYPE_INVALID) PrettyError("MarkAsDone()/IsMarkedAsDone() is being used with an invalid object type (perhaps the module object). Item scripts are prone to do this."); } // done flags int IsMarkedAsDone(object oObject=OBJECT_SELF, int iFlag=0) { DoneFlagSanityCheck(oObject); int iDoneOnce = GetLocalInt(oObject, GetDoneFlag(iFlag)); return (iDoneOnce); } void MarkAsDone(object oObject=OBJECT_SELF, int iFlag=0) { DoneFlagSanityCheck(oObject); SetLocalInt(oObject, GetDoneFlag(iFlag), TRUE); } // *** Global Array Functions // Returns a string, from nVarNum in the array string GetGlobalArrayString(string sVarName, int nVarNum) { string sFullVarName = sVarName + IntToString(nVarNum) ; return GetGlobalString(sFullVarName); } // Sets the string at nVarNum position void SetGlobalArrayString(string sVarName, int nVarNum, string nValue) { string sFullVarName = sVarName + IntToString(nVarNum) ; SetGlobalString(sFullVarName, nValue); } // Returns an integer, from nVarNum in the array int GetGlobalArrayInt(string sVarName, int nVarNum) { string sFullVarName = sVarName + IntToString(nVarNum) ; return GetGlobalInt(sFullVarName); } // Sets the integer at nVarNum position void SetGlobalArrayInt(string sVarName, int nVarNum, int nValue) { string sFullVarName = sVarName + IntToString(nVarNum) ; SetGlobalInt(sFullVarName, nValue); } // ginc_wp /* Standard include for scripted waypoints The functions are organized by job-related categories. General utility funtions are listed first, the rest of the sections are listed in alphabetical order according to job category. */ // ChazM 1/6/06 // ChazM 1/7/07 updated GetPreviousWaypoint(), SetCurrentWaypoint(), and GetCurrentWaypoint() to // GetCurrentWaypoint(), SetNextWaypoint(), and GetNextWaypoint() by popular demand // ChazM 1/10/06 Added Conversation section // ChazM 1/11/06 Added Travel Section // ChazM 1/17/06 Added RollDice() // ChazM 1/19/06 Added GetWaypointString(), GetWaypointRangeString(), SelectRandomWaypointFromString(), // modified RandomOnwardWaypoint(), GetRandomWaypoint() // ChazM 1/20/06 included ginc_item // ChazM 1/24/06 Added StandardRedirectorNode(), StandardRoadNetworkNode(), JumpToNextWP() // DBR 2/13/06 Standardized RandomFloat() // ChazM 3/08/06 Modified StandardRedirectorNode(), StandardRoadNetworkNode() - added back in the script hidden stuff #include "x0_i0_walkway" #include "ginc_actions" #include "x0_i0_stringlib" #include "ginc_item" #include "ginc_math" //void main(){} // ===================================================================================== // Prototypes // ===================================================================================== /* // some useful functions in x0_i0_walkway: void ForceResumeWWP(object oCreature=OBJECT_SELF); int GetNumWaypoints(object oCreature=OBJECT_SELF); int GetNumWaypointsByPrefix(string sPrefix, object oCreature=OBJECT_SELF); void SetNextWaypoint(int iNextWP); int GetNextWaypoint(); int GetCurrentWaypoint(); int GetPreviousWaypoint(); object GetWaypointByNum(int iWayPoint, object oCreature=OBJECT_SELF); string GetWPPrefix(object oCreature = OBJECT_SELF); int GetWalkCondition(int nCondition, object oCreature=OBJECT_SELF);// Get whether the condition is set void SetWalkCondition(int nCondition, int bValid=TRUE, object oCreature=OBJECT_SELF);// Set a given condition */ // GENERAL void FaceAndPause(int iWayPoint, float fPause = 1.0f); void ActionSpeakOneLiner(string sConversation = ""); // CONVERSATION int RandomTalkAnim(); int RandomVictoryAnim(); int RandomPauseAnim(); int RandomInteractionAnim(); int AnimationNeedsWait(int iAnimation); void AnimateWithOther(object oOther, float fDurationSeconds=5.0f, int iAnimation=ANIMATION_LOOPING_TALK_NORMAL, int iOtherAnimation=ANIMATION_LOOPING_LISTEN, float fSpeed=1.0f); void TalkToListener(object oListener, float fDurationSeconds=5.0f, int iTalkerAnimation=ANIMATION_LOOPING_TALK_NORMAL); void ListenToTalker(object oListener, float fDurationSeconds=5.0f, int iTalkerAnimation=ANIMATION_LOOPING_TALK_NORMAL); void MutualGreeting(object oOther, float fDurationSeconds=2.0f); void RandomInteractionExchange(object oOther, int iFreq=3, int iRand=7, int iDelta=3); void StandardExchange(object oOther, int iAnimation, int iRand=7, int iDelta=3); void AngryTalk(object oOther, int iRand=7, int iDelta=3); void TypicalTalk(object oOther, int iRand=7, int iDelta=3); void InitiateConversation(object oOther); void ShortConversation(object oOther); // FARMING void RandomFarmAction(); void TypicalFarmer(); // LABOR void LookInCrate(object oCrate); // TRAVEL // waypoint string are 2 digits, seperated by commas const int WAYPOINT_ENTY_LENGTH = 3; // 2 digits + a comma delimiter const int WAYPOINT_DIGITS = 2; // returns a waypoint in the string format used by SelectRandomWaypointFromString() string GetWaypointString(int iWP, int iExcludedWP=-1); // returns string w/ all waypoints in the range iMinWP - iMaxWP string GetWaypointRangeString(int iMinWP, int iMaxWP, int iExcludedWP=-1); // Returns a random num from a delimited list. int SelectRandomWaypointFromString(string sWPString, int iExcludedWP=-1); // get random waypoint from set of all waypoints other than the current one. int GetRandomWaypoint(int bExcludeCurrent = TRUE); // pick a random num that isn't a default value or the previous wp. int RandomOnwardWaypoint(int iWP1, int iWP2=-1, int iWP3=-1, int iWP4=-1, int iWP5=-1); // ===================================================================================== // Functions // ===================================================================================== // ------------------------------------------------------------------------------------- // GENERAL // ------------------------------------------------------------------------------------- // faces the waypoint and waits a default of 1 sec - replicates NWN1 WWP void FaceAndPause(int iWayPoint, float fPause = 1.0f) { object oWay = GetWaypointByNum(iWayPoint); ActionDoCommand(SetFacing(GetFacing(oWay))); ActionWait(fPause); } // put "speak one liner" on action queue void ActionSpeakOneLiner(string sConversation = "") { ActionDoCommand(SpeakOneLinerConversation(sConversation)); // ActionSpeakString } int RollDice (int iNumDice, int iNumSides, int iModifier = 0) { int iTotal = iModifier; int i; for (i=1; i<= iNumDice; i++) { iTotal += Random(iNumSides)+1; } return (iTotal); } // ------------------------------------------------------------------------------------- // CONVERSATION // ------------------------------------------------------------------------------------- int RandomTalkAnim() { int nReaction = Random(4) + 1; int iAction; switch(nReaction) { case 1: iAction = ANIMATION_LOOPING_TALK_PLEADING; break; case 2: iAction = ANIMATION_LOOPING_TALK_FORCEFUL; break; case 3: iAction = ANIMATION_LOOPING_TALK_NORMAL; break; case 4: iAction = ANIMATION_LOOPING_TALK_LAUGHING; break; } return (iAction); } int RandomVictoryAnim() { int nReaction = Random(3) + 1; int iAction; switch(nReaction) { case 1: iAction = ANIMATION_FIREFORGET_VICTORY1; break; case 2: iAction = ANIMATION_FIREFORGET_VICTORY2; break; case 3: iAction = ANIMATION_FIREFORGET_VICTORY3; break; } return (iAction); } int RandomPauseAnim() { int nReaction = Random(6) + 1; int iAction; switch(nReaction) { case 1: iAction = ANIMATION_LOOPING_PAUSE; break; case 2: iAction = ANIMATION_LOOPING_PAUSE2; break; case 3: iAction = ANIMATION_LOOPING_PAUSE_TIRED; break; case 4: iAction = ANIMATION_LOOPING_PAUSE_DRUNK; break; case 5: iAction = ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD; break; case 6: iAction = ANIMATION_FIREFORGET_PAUSE_BORED; break; } return (iAction); } int RandomInteractionAnim() { int nReaction = Random(5) + 1; int iAction; switch(nReaction) { case 1: iAction = RandomPauseAnim(); break; case 2: //cheer iAction = RandomVictoryAnim(); break; case 3: //nod iAction = ANIMATION_FIREFORGET_READ; break; case 4: //bow iAction = ANIMATION_FIREFORGET_BOW; break; case 5: iAction = RandomTalkAnim(); break; } return (iAction); } int AnimationNeedsWait(int iAnimation) { int iRet = FALSE; if ((iAnimation > 100) || (iAnimation == ANIMATION_LOOPING_LISTEN)) iRet = TRUE; return(iRet); } // I animate and so does another object. If Fire & Forget anims, then use waits to keep on same track. void AnimateWithOther(object oOther, float fDurationSeconds=5.0f, int iAnimation=ANIMATION_LOOPING_TALK_NORMAL, int iOtherAnimation=ANIMATION_LOOPING_LISTEN, float fSpeed=1.0f) { ActionPlayAnimation(iAnimation, fSpeed, fDurationSeconds); if (AnimationNeedsWait(iAnimation)) ActionWait(fDurationSeconds); AssignCommand(oOther, ActionPlayAnimation(iOtherAnimation, fSpeed, fDurationSeconds)); if (AnimationNeedsWait(iOtherAnimation)) AssignCommand(oOther, ActionWait(fDurationSeconds)); } void TalkToListener(object oListener, float fDurationSeconds=5.0f, int iTalkerAnimation=ANIMATION_LOOPING_TALK_NORMAL) { AnimateWithOther(oListener, fDurationSeconds, iTalkerAnimation); } void ListenToTalker(object oListener, float fDurationSeconds=5.0f, int iTalkerAnimation=ANIMATION_LOOPING_TALK_NORMAL) { AnimateWithOther(oListener, fDurationSeconds, ANIMATION_LOOPING_LISTEN, iTalkerAnimation); } void MutualGreeting(object oOther, float fDurationSeconds=2.0f) { AnimateWithOther(oOther, fDurationSeconds, ANIMATION_FIREFORGET_GREETING, ANIMATION_FIREFORGET_GREETING); } // exchanges are 1 round where both parties both talk and listen void RandomInteractionExchange(object oOther, int iFreq=3, int iRand=7, int iDelta=3) { if(Random(iFreq) == 0) { float fDurationSeconds = RandomFloat(IntToFloat(iRand))+ iDelta; TalkToListener(oOther, fDurationSeconds, RandomTalkAnim()); fDurationSeconds = RandomFloat(IntToFloat(iRand))+ iDelta; ListenToTalker(oOther, fDurationSeconds, RandomInteractionAnim()); } } void StandardExchange(object oOther, int iAnimation, int iRand=7, int iDelta=3) { float fDurationSeconds = RandomFloat(IntToFloat(iRand))+ iDelta; TalkToListener(oOther, fDurationSeconds, iAnimation); fDurationSeconds = RandomFloat(IntToFloat(iRand)) + iDelta; ListenToTalker(oOther, fDurationSeconds, iAnimation); RandomInteractionExchange(oOther); } // Talk encompass multiple exchanges void AngryTalk(object oOther, int iRand=7, int iDelta=3) { StandardExchange(oOther, ANIMATION_LOOPING_TALK_FORCEFUL); RandomInteractionExchange(oOther); } void TypicalTalk(object oOther, int iRand=7, int iDelta=3) { StandardExchange(oOther, RandomTalkAnim()); RandomInteractionExchange(oOther); } void InitiateConversation(object oOther) { // approach object oSelf = OBJECT_SELF; ActionMoveToObject(oOther); AssignCommand(oOther, ActionMoveToObject(oSelf)); ActionOrientToObject(oOther, ORIENT_FACE_TARGET); AssignCommand(oOther, ActionOrientToObject(oSelf, ORIENT_FACE_TARGET)); } // conversations are like talks, but are complete and may contain greetings and/or salutations void ShortConversation(object oOther) { // hello MutualGreeting(oOther); // approach InitiateConversation(oOther); // talk TypicalTalk(oOther); TypicalTalk(oOther); // goodbye MutualGreeting(oOther); } // ------------------------------------------------------------------------------------- // FARMING // ------------------------------------------------------------------------------------- void RandomFarmAction() { int iAction = Random(5); float fDuration = IntToFloat(Random(5)+3); switch (iAction) { case 0: case 1: ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, fDuration); break; case 2: case 3: ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, fDuration); break; case 4: ActionPlayAnimation(ANIMATION_LOOPING_PAUSE_TIRED, 1.0, fDuration); break; } } void TypicalFarmer() { SetNextWaypoint(GetRandomWaypoint()); RandomFarmAction(); ActionMoveAwayFromLocation(GetLocation(OBJECT_SELF),FALSE, IntToFloat(Random(2)+1)); RandomFarmAction(); } // ------------------------------------------------------------------------------------- // LABOR // ------------------------------------------------------------------------------------- void LookInCrate(object oCrate) { ActionMoveToObject(oCrate); // ActionInteractObject(oCrate); ActionDoCommand(AssignCommand(oCrate, PlayAnimation(ANIMATION_PLACEABLE_OPEN))); ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, RandomFloat(IntToFloat(6))+3); ActionDoCommand(AssignCommand(oCrate, PlayAnimation(ANIMATION_PLACEABLE_CLOSE))); ActionMoveAwayFromObject(oCrate, FALSE, RandomFloat(IntToFloat(3))+ 1); ActionWait(RandomFloat(IntToFloat(2))+ 1); } // ------------------------------------------------------------------------------------- // TRAVEL // ------------------------------------------------------------------------------------- // returns a waypoint in the string format used by SelectRandomWaypointFromString() string GetWaypointString(int iWP, int iExcludedWP=-1) { if ((iWP < 0) ||(iWP == iExcludedWP)) return ""; else return GetWaypointSuffix(iWP) + ","; } // returns string w/ all waypoints in the range iMinWP - iMaxWP string GetWaypointRangeString(int iMinWP, int iMaxWP, int iExcludedWP=-1) { int i; string sWPString = ""; for (i=iMinWP; i <= iMaxWP; i++) { sWPString += GetWaypointString(i, iExcludedWP); } return (sWPString); } // Returns a random num from a delimited list. // returns 0 if can't find anything. // string should be in the format "XX,YY,ZZ..." // a final comma is allowed but not required. int SelectRandomWaypointFromString(string sWPString, int iExcludedWP=-1) { // add 1 to string length to account for possibly having no ending comma int iChoice = Random((GetStringLength(sWPString)+1)/WAYPOINT_ENTY_LENGTH); string sWP = GetSubString(sWPString, iChoice*WAYPOINT_ENTY_LENGTH, WAYPOINT_DIGITS); int iWP = StringToInt(sWP); // iWP will be 0 if we can't get a number out of the string. while ((iWP == iExcludedWP) && (iWP != 0)) { sWPString = RemoveListElement(sWPString, sWP); // remove waypoint from list iChoice = Random((GetStringLength(sWPString)+1)/WAYPOINT_ENTY_LENGTH); sWP = GetSubString(sWPString, iChoice*WAYPOINT_ENTY_LENGTH, WAYPOINT_DIGITS); iWP = StringToInt(sWP); } return(iWP); } // get random waypoint from set of all waypoints int GetRandomWaypoint(int bExcludeCurrent = TRUE) { int iNumWaypoints = GetNumWaypoints(); int iCurrentWP = GetCurrentWaypoint(); int iNextWP = Random(iNumWaypoints) + 1; // if quick way failed, do long way. if (bExcludeCurrent && (iNextWP == iCurrentWP) ) { string sWPString = GetWaypointRangeString(1, iNumWaypoints, iCurrentWP); iNextWP = SelectRandomWaypointFromString(sWPString); } return (iNextWP); } // pick a random num that isn't a default value or the previous wp. int RandomOnwardWaypoint(int iWP1, int iWP2=-1, int iWP3=-1, int iWP4=-1, int iWP5=-1) { int iWPCount; int iPrevWP = GetPreviousWaypoint(); string sWPString = ""; sWPString += GetWaypointString(iWP1, iPrevWP); sWPString += GetWaypointString(iWP2, iPrevWP); sWPString += GetWaypointString(iWP3, iPrevWP); sWPString += GetWaypointString(iWP4, iPrevWP); sWPString += GetWaypointString(iWP5, iPrevWP); int iWP = SelectRandomWaypointFromString(sWPString); //int iChoice = Random(GetStringLength(sWPString)/2); //int iWP = StringToInt(GetSubString(sWPString, iChoice*2, 2)); //PrettyDebug(GetName(OBJECT_SELF) + " WP string: " + sWPString); return (iWP); } void JumpToNextWP(int iWP) { SetNextWaypoint (iWP); ActionJumpToObject(GetWaypointByNum(iWP)); } // function for nodes void StandardRoadNetworkNode(string sWPString, int iRedirecterWP) { int iPrevWP = GetPreviousWaypoint(); int iWP = SelectRandomWaypointFromString(sWPString, iPrevWP); //PrettyDebug ("iWP = " + IntToString (iWP)); if (0 == iWP) { ActionDoCommand(SetScriptHidden(OBJECT_SELF, TRUE, FALSE));// hide myself ActionWait(1.0f); //SetScriptHidden(OBJECT_SELF, TRUE); JumpToNextWP(iRedirecterWP); } else SetNextWaypoint(iWP); } // function for the redirector waypoint void StandardRedirectorNode(string sWPString, float fWaitTime) { int iPrevWP = GetPreviousWaypoint(); int iWP = SelectRandomWaypointFromString(sWPString, iPrevWP); if (0 == iWP) { PrettyDebug ("No where to go from StandardRedirectorNode()"); } else { EquipRandomArmorFromInventory(); ActionWait(fWaitTime); JumpToNextWP(iWP); ActionWait(1.0f); ActionDoCommand(SetScriptHidden(OBJECT_SELF, FALSE));// show myself again //SetScriptHidden(OBJECT_SELF, FALSE);// show myself again } } Global Placeables // gp_forgemagic_ca /* forge magic weapons on spell cast */ // ChazM 12/15/05 // ChazM 3/28/06 Crafting call interface change #include "ginc_crafting" void main() { int iSpellID = GetLastSpell(); // returns the SPELL_* that was cast. object oCaster = GetLastSpellCaster(); // returns the object that cast the spell. output ("iSpellID = " + IntToString(iSpellID), oCaster); //output ("iSpellID = " + IntToString(iSpellID)); DoMagicCrafting(iSpellID, oCaster); } //gp_goldpile_use // Global script for on use of a gold pile. (Gives player X amount of gold, destroys goldpile placeable) // DBR 8/15/06 //To use - put this script on the "onUsed" event of a goldpile placeable, make sure the placeable is Usable and non-static. Also make sure the HP of the placeable is not zero. //To override the maximum and minimum ranges, put integer variables "nGoldRangeMax" and "nGoldRangeMin" on the placeable with the new value. string sGOLDRANGE_MAX = "nGoldRangeMax"; //Defaults to 300, 0 is not a valid entry. string sGOLDRANGE_MIN = "nGoldRangeMin"; //Defaults to 100, if MAX is specified it will default to 1/3 of that, 0 is not a valid entry. string sUSES_LEFT = "nUsesLeft"; //Defaults to 1, 0 is not a valid entry. void main() { int nUsesLeft = GetLocalInt(OBJECT_SELF,sUSES_LEFT); //if zero, assume the value is uninitialized. SetLocalInt(OBJECT_SELF,sUSES_LEFT,nUsesLeft-1); if (nUsesLeft>=0) { int nGoldRangeMax = GetLocalInt(OBJECT_SELF,sGOLDRANGE_MAX); int nGoldRangeMin = GetLocalInt(OBJECT_SELF,sGOLDRANGE_MIN); if (nGoldRangeMax == 0) nGoldRangeMax = 300; if (nGoldRangeMin == 0) nGoldRangeMin = nGoldRangeMax/3; int nGP = Random(nGoldRangeMax-nGoldRangeMin)+nGoldRangeMin; object oPC = GetLastUsedBy(); GiveGoldToCreature(oPC,nGP); } if (nUsesLeft<=1) { AssignCommand(OBJECT_SELF,DestroyObject(OBJECT_SELF)); } } // gp_ipcleaner_hb.nss /* Heartbeat handler to clean up area after combat cutscene has ended. Used in conjunction with ginc_cutscene's CombatCutsceneSetup(); */ // BMA-OEI 3/7/06 #include "ginc_cutscene" #include "ginc_debug" void main() { AttemptCombatCutsceneCleanUp(); QueueCombatCutsceneCleanUp(); } // gp_ipspeaker_hb /* Heartbeat handler to start conversation with the PC when conditions are safe. Safe being, NPC speaker and PC (including faction) are not in combat nor in conversation. Used with gg_death_talk.nss (GroupOnDeathBeginConversation) */ // BMA-OEI 1/24/06 #include "ginc_debug" #include "ginc_ipspeaker" #include "ginc_cutscene" void main() { IPSpeakerHeartbeat(); } // gp_output_2da /* output 2da data for crafting to the log file */ // ChazM 2/2/06 // ChazM 3/1/06 - Restructured to call self multiple times so we don't run out of instructions. #include "ginc_crafting" const string VAR_REC_SET_2DA = "VAR_REC_SET_2DA"; const string SETUP_COUNT_2DA = "SETUP_COUNT_2DA"; const int MAX_RECIPE_PROCESSING_COUNT = 50; // output all recipes of specific type, using the list of indexes to find them all // returns remaining sIndexList if we run over MAX_RECIPE_PROCESSING_COUNT string OutputRecipeTypePortion(string sRecipePrefix, string sIndexList) { //output ("OutputRecipeType: sRecipePrefix: " + sRecipePrefix + " sIndexList:" + sIndexList); string sIndex; struct sStringTokenizer stTok = GetStringTokenizer(sIndexList, ","); int iRecipeCount = 0; // loop through recipe index list while (HasMoreTokens(stTok) && iRecipeCount=nDC) { PlayVoiceChat(VOICE_CHAT_LOOKHERE, oSearcher); //I found something! return 1; } return 0; } void ResetSecretObject() { if (GetLocalInt(OBJECT_SELF,"SECRET_OBJECT_APPEARED")==0) return; if (WasObjectDetected()) { DelayCommand(GetLocalFloat(OBJECT_SELF,sID_TIMETORESET),ResetSecretObject()); return; } object oSecret=GetLocalObject(OBJECT_SELF,sID_SECRET_NEW_OBJECT); string sReplacedResRef=GetLocalString(OBJECT_SELF,sID_REPLACED_RESREF); location lReplacedLoc=GetLocalLocation(OBJECT_SELF,sID_REPLACED_LOCATION); int nReplacedObjectType=GetLocalInt(OBJECT_SELF,sID_REPLACED_OBJECT_TYPE); DestroyObject(oSecret); //out with the new object oReplaced; if (sReplacedResRef!="") //in with the old oReplaced=CreateObject(nReplacedObjectType,sReplacedResRef,lReplacedLoc,TRUE); DeleteLocalInt(OBJECT_SELF,"SECRET_OBJECT_APPEARED"); string sTag=GetTag(OBJECT_SELF),sPair; //are we paired? int nLen = GetStringLength(sTag); string sNewTag = GetStringLeft(sTag, nLen - 1); if(GetStringRight(sTag, 1) == "a") sPair=sNewTag + "b"; else sPair=sNewTag + "a"; object oPair=GetObjectByTag(sPair); if (GetIsObjectValid(oPair)) //paired doors AssignCommand(oPair,ResetSecretObject()); } void RevealObject() { if (GetLocalInt(OBJECT_SELF,"SECRET_OBJECT_APPEARED")==1) //redundent check for double door safety return; location lLoc = GetLocation (OBJECT_SELF); string sNewTag=GetLocalString(OBJECT_SELF,sID_NEWTAG); object oSpawn; string sSpawnResRef = GetLocalString(OBJECT_SELF,sID_RESREF); //Create ResRef if (sSpawnResRef!="") //create object { oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE,sSpawnResRef,lLoc,TRUE,sNewTag); if (!GetIsObjectValid(oSpawn)) oSpawn = CreateObject(OBJECT_TYPE_ITEM,sSpawnResRef,lLoc,TRUE,sNewTag); if (!GetIsObjectValid(oSpawn)) oSpawn = CreateObject(OBJECT_TYPE_CREATURE,sSpawnResRef,lLoc,TRUE,sNewTag); if (!GetIsObjectValid(oSpawn)) { PrintString("gp_secretobject_hb: ERROR, Cannot find ResRef: "+sSpawnResRef); DelayCommand(0.2f,DestroyObject(OBJECT_SELF)); return; } int nEffect=GetLocalInt(OBJECT_SELF,sID_VFX); //what effect? if (nEffect!=-1) { effect eVis = EffectVisualEffect(nEffect); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVis,oSpawn,10.0f); } //STORE NEW OBJECT'S POINTER FOR RESETTING SetLocalObject(OBJECT_SELF,sID_SECRET_NEW_OBJECT,oSpawn); } string sJumpToTag = GetLocalString(OBJECT_SELF,sID_JUMPTO_TAG);//Used for secret doors if (sJumpToTag!="") { object oDest=GetObjectByTag(sJumpToTag); SetLocalObject(oSpawn,"DOOR_DESTINATION",oDest); //SetEventHandler(oSpawn,On used event, on used script); TO BE IMPLEMENTED LATER string sTag=GetTag(OBJECT_SELF), sPair; //are we paired? int nLen = GetStringLength(sTag); string sNewTag = GetStringLeft(sTag, nLen - 1); if(GetStringRight(sTag, 1) == "a") sPair=sNewTag + "b"; else sPair=sNewTag + "a"; object oPair=GetObjectByTag(sPair); if (GetIsObjectValid(oPair)) //paired doors AssignCommand(oPair,RevealObject()); } //Replacement bits string sReplaceTag = GetLocalString(OBJECT_SELF,sID_REPLACE_TAG); if (sReplaceTag!="") { object oReplace = GetObjectByTag(sReplaceTag); SetLocalString(OBJECT_SELF,sID_REPLACED_RESREF,GetResRef(oReplace)); SetLocalLocation(OBJECT_SELF,sID_REPLACED_LOCATION,GetLocation(oReplace)); SetLocalInt(OBJECT_SELF,sID_REPLACED_OBJECT_TYPE,GetObjectType(oReplace)); DestroyObject(oReplace); } //Reset bits float fTimeToReset=GetLocalFloat(OBJECT_SELF,sID_TIMETORESET); if (fTimeToReset>0.0f) DelayCommand(fTimeToReset,ResetSecretObject()); SetLocalInt(OBJECT_SELF,"SECRET_OBJECT_APPEARED",1); string sScript=GetLocalString(OBJECT_SELF,sID_SCRIPT); //in case script is provided if (sScript!="") ExecuteScript(sScript,OBJECT_SELF); } int WasObjectDetected() { // get the radius and DC of the secret door. float fSearchDist = GetLocalFloat(OBJECT_SELF,sID_SEARCH_RADIUS); // what is the tag of this object used in setting the destination string sTag = GetTag(OBJECT_SELF); int nCount = 1; object oNearestCreature = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE); while (oNearestCreature != OBJECT_INVALID) { if(GetIsPC(GetMaster(oNearestCreature)) || GetIsPC(oNearestCreature)) { // what is the distance of the PC to the door location float fDist = GetDistanceBetween(OBJECT_SELF,oNearestCreature); if (fDist <= fSearchDist) if (LineOfSightObject(OBJECT_SELF, oNearestCreature) == TRUE) if (CheckIfDetected(oNearestCreature)) return 1; } nCount++; oNearestCreature = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF ,nCount); } return 0; } void main() { int nAppeared = GetLocalInt(OBJECT_SELF, "SECRET_OBJECT_APPEARED"); if(nAppeared == 1) return; if (WasObjectDetected()) RevealObject(); } // gp_talk_door // // Start a conversation with a door. // EPF 10/28/05 void main() { object oUser = GetClickingObject(); ActionStartConversation(oUser); } // gp_talk_object.nss /* This script allows you to speak to an object. Set a conversation, set Usable to True, and attach this script to the OnUsed event. */ // FAB 2/7 // ChazM 2/17/05 // BMA-OEI 9/17/05 file description void main() { object oUser = GetLastUsedBy(); ActionStartConversation(oUser); } // gp_treasure_op_de /* Spawns in general purpose treasure and gold based on variables: TreasureClass - one of three values. Default is low const int X2_DTS_CLASS_LOW = 0; //Treasure Class Low const int X2_DTS_CLASS_MEDIUM = 1; //Treasure Clas Medium const int X2_DTS_CLASS_HIGH = 2; //Treasure Class High TreasureType - add desired types together. For example, gold + disposable = 5 Defualt is 5 (gold + disp) Note that you cannot add the same type more than once (i.e. no gold+gold). const int X2_DTS_TYPE_DISP = 1; const int X2_DTS_TYPE_AMMO = 2; const int X2_DTS_TYPE_GOLD = 4; // actually gold and gems (not allowed) const int X2_DTS_TYPE_ITEM = 8; // char specific Item (ignores treasure class) const int X2_DTS_TYPE_MAGIC = 16; // random magic items const int X2_DTS_TYPE_MUNDANE = 32; // random mundane items This script should be placed in the container's OnOpen and OnDeath events. If bashed, disposeable will be dropped and broken item generated. If no treasures are generated, 1d20 gold will be created. */ // ChazM 5/26/06 // ChazM 7/31/06 Added broken items when bashing // ChazM 8/7/06 Generate smidgen of gold if nothing else was generated. Set broken item to proper resref. // ChazM 8/30/06 Fixed broken item res ref. // ChazM 9/5/06 Disallowed treasure type X2_DTS_TYPE_ITEM #include "x2_inc_treasure" #include "nw_o2_coninclude" #include "x2_inc_compon" #include "ginc_debug" const string BROKEN_ITEM_RES_REF = "n2_it_brokenitem"; // the catch-all broken item const string GOLD_ITEM_RES_REF = "nw_it_gold001"; // gold! // local ints stored on the chest const string VAR_TREASURE_CLASS = "TreasureClass"; const string VAR_TREASURE_TYPE = "TreasureType"; void main() { // craft_drop_placeable(); if (GetLocalInt(OBJECT_SELF,"NW_DO_ONCE") != 0) { return; } object oOpener = GetLastOpener(); int iTreasureClass = GetLocalInt(OBJECT_SELF, VAR_TREASURE_CLASS); int iTreasureType = GetLocalInt(OBJECT_SELF, VAR_TREASURE_TYPE); if (iTreasureType == 0) iTreasureType = X2_DTS_TYPE_DISP | X2_DTS_TYPE_GOLD; // if bashed, replace disposable w/ broken item //PrettyDebug("GetLastKiller() = " + GetName(GetLastKiller())); // remove Tresure Type "Item" - these don't scale and are to dangerous for balance reasons // to have in the standard treasure generation if (iTreasureType & X2_DTS_TYPE_ITEM) { PrettyError("This container, " + GetTag(OBJECT_SELF) + ", is attempting to use X2_DTS_TYPE_ITEM which is not allowed. Please report as an error. (This info also output to log)"); iTreasureType = iTreasureType & (~X2_DTS_TYPE_ITEM); } if (GetIsObjectValid(GetLastKiller())) { //PrettyDebug("creating broken item and removing disposeable"); iTreasureType = iTreasureType & (~X2_DTS_TYPE_DISP); CreateItemOnObject(BROKEN_ITEM_RES_REF, OBJECT_SELF, 1); } int iNumGenerated = DTSGenerateTreasureOnContainer (OBJECT_SELF, oOpener, iTreasureClass, iTreasureType); //PrettyDebug("iNumGenerated = " + IntToString(iNumGenerated)); // everything must have something... // if we didn't generate anything then add a smidgen of gold if (iNumGenerated == 0) { CreateItemOnObject(GOLD_ITEM_RES_REF, OBJECT_SELF, d20(1)); } SetLocalInt(OBJECT_SELF,"NW_DO_ONCE",1); ShoutDisturbed(); } Global Reports // gr /* Starts the gr_convo which gives access to the various gr_* scripts This script for use with the dm_runscript console command */ // ChazM 11/6/05 void main() { //object oLeader = GetFactionLeader(OBJECT_SELF); //if (GetIsObjectValid(oLeader) == TRUE) //{ AssignCommand(OBJECT_SELF, ActionStartConversation(OBJECT_SELF, "gr_convo", TRUE, FALSE)); //} } // gr_character_xml /* output character data to the log in XML format */ // ChazM 10/30/06 // ChazM 10/31/06 - Lots of additions // ChazM 11/2/06 - Fixed classes tag // ChazM 11/8/06 - Added new fields under skills, modified XML tabbing // ChazM 11/10/06 - Added Spell Class Levels #include "ginc_debug" #include "ginc_vars" #include "x2_inc_craft" // ---------------------------------------- // XML Tags // ---------------------------------------- // Output Text (convert to str refs eventually... const string TEXT_TRUE = "TRUE"; const string TEXT_FALSE = "FALSE"; // character XML const string TAG_CHARACTER = "Character"; // Basic stats XML const string TAG_FIRST_NAME = "FirstName"; const string TAG_LAST_NAME = "LastName"; const string TAG_PLAYER_NAME = "PlayerName"; const string TAG_ALIGNMENT = "Alignment"; const string TAG_ALIGNMENT_LC_CONST = "LawChaosConst"; const string TAG_ALIGNMENT_LC = "LawChaos"; const string TAG_ALIGNMENT_GE_CONST = "GoodEvilConst"; const string TAG_ALIGNMENT_GE = "GoodEvil"; const string TAG_GOLD = "Gold"; const string TAG_EXPERIENCE = "Experience"; const string TAG_AGE = "Age"; const string TAG_ARMOR_CLASS = "ArmorClass"; const string TAG_BASE_ATTACK_BONUS = "BaseAttackBonus"; const string TAG_HIT_POINTS = "HitPoints"; const string TAG_GENDER = "Gender"; const string TAG_RACE = "Race"; const string TAG_FORT_SAVE = "FortSave"; const string TAG_WILL_SAVE = "WillSave"; const string TAG_REFLEX_SAVE = "ReflexSave"; // abilities XML const string TAG_ABILITIES = "Abilities"; const string TAG_ABILITY = "Ability"; const string TAG_ABILITY_NAME = "Name"; const string TAG_ABILITY_SCORE = "Score"; const string TAG_ABILITY_MODIFIER = "Modifier"; // inventory/equipment XML const string TAG_INVENTORY_ITEMS = "Equipment"; const string TAG_EQUIPPED_ITEMS = "Equipped"; const string TAG_ITEM = "Item"; const string TAG_ITEM_TYPE = "Type"; const string TAG_ITEM_NAME = "Name"; const string TAG_ITEM_WEIGHT = "Weight"; const string TAG_ITEM_STACK_SIZE = "StackSize"; const string TAG_ITEM_AC_VALUE = "ACValue"; const string TAG_ITEM_CHARGES = "Charges"; const string TAG_ITEM_PROPERTIES = "ItemProperties"; const string TAG_ITEM_PROPERTY = "ItemProperty"; const string TAG_ITEM_PROPERTY_TYPE = "ItemPropertyType"; const string TAG_ITEM_PROPERTY_PARAM1 = "ItemPropertyParam1"; const string TAG_ITEM_PROPERTY_PARAM2 = "ItemPropertyParam2"; const string TAG_ITEM_PROPERTY_PARAM3 = "ItemPropertyParam3"; const string TAG_ITEM_PROPERTY_PARAM4 = "ItemPropertyParam4"; // skills XML const string TAG_SKILLS = "Skills"; const string TAG_SKILL = "Skill"; const string TAG_SKILL_NAME = "Name"; const string TAG_SKILL_RANK = "Rank"; const string TAG_SKILL_RANK_BASE = "Base"; const string TAG_SKILL_TRAINED = "Trained"; const string TAG_SKILL_SPECIALTY = "Specialty"; const string TAG_SKILL_DESCRIPTION = "Description"; // Feats XML const string TAG_FEATS = "Feats"; const string TAG_FEAT = "Feat"; const string TAG_FEAT_NAME = "Name"; const string TAG_FEAT_DESCRIPTION = "Description"; // Spells XML const string TAG_SPELLS_MEMORIZED = "SpellsMemorized"; const string TAG_SPELL = "Spell"; const string TAG_SPELL_NAME = "Name"; const string TAG_SPELL_INNATE_LEVEL = "InnateLevel"; const string TAG_SPELL_DESCRIPTION = "Description"; const string TAG_SPELL_CLASS_LEVELS = "ClassLevels"; const string TAG_SPELL_CLASS_LEVEL = "ClassLevel"; const string TAG_SPELL_CLASS = "Class"; const string TAG_SPELL_LEVEL = "Level"; // Classes XML const string TAG_CLASSES = "Classes"; const string TAG_CLASS = "Class"; const string TAG_CLASS_NAME = "ClassName"; const string TAG_CLASS_LEVEL = "ClassLevel"; // ---------------------------------------- // Various Constants // ---------------------------------------- const string LF = ""; const string TAB = " "; const int TAB_SPACES = 4; // 1 2 3 4 5 6 7 8 9 0 // 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 const string BLANK_SPACE_100 = " "; // ---------------------------------------- // 2da constants // ---------------------------------------- // skills 2da const string SKILLS_2DA = "skills"; // 2da const int SKILLS_ROW_COUNT = 29; // number of rows in the skills table. const string SKILLS_NAME_COL = "Name"; // str ref of skill name const string SKILLS_DESC_COL = "Description"; // str ref of skill description // feat 2da const string FEATS_2DA = "feat"; // 2da const int FEATS_ROW_COUNT = 1859; // number of rows in the feats table. const string FEATS_NAME_COL = "FEAT"; // str ref of feat name const string FEATS_DESC_COL = "DESCRIPTION"; // str ref of feat description // spells 2da (in x2_inc_craft) //const string SPELLS_2DA = "spells"; // 2da //const int SPELLS_ROW_COUNT = 1008; // number of rows in the spells table. //const string SPELLS_NAME_COL = "Name"; // str ref of spell name //const string SPELLS_DESC_COL = "SpellDesc"; // str ref of spell description //const string SPELLS_INNATE_LEVEL_COL = "Innate"; //Innate level of spell // classes 2da const string CLASSES_2DA = "classes"; // 2da const int CLASSES_ROW_COUNT = 56; // number of rows in the classes table. const string CLASSES_NAME_COL = "Name"; // str ref of class name const string CLASSES_DESC_COL = "Description"; // str ref of class description // itemprops 2da const string ITEM_PROPS_2DA = "itemprops"; // 2da const int ITEM_PROPS_ROW_COUNT = 89; // number of rows in the itemprops table. const string ITEM_PROPS_NAME_COL = "StringRef"; // str ref of itemprops name // races 2da const string RACES_2DA = "racialtypes"; // 2da const int RACES_ROW_COUNT = 30; // number of rows in the races table. const string RACES_NAME_COL = "Name"; // str ref of race name // sub races 2da const string SUB_RACES_2DA = "racialsubtypes"; // 2da const int SUB_RACES_ROW_COUNT = 46; // number of rows in the sub races table. const string SUB_RACES_NAME_COL = "Name"; // str ref of sub race name //Base Item Types 2da const string BIT_2DA = "baseitems"; // 2da const int BIT_ROW_COUNT = 143; // number of rows in the BIT table. const string BIT_NAME_COL = "Name"; // str ref of BIT name // ---------------------------------------- // globals // ---------------------------------------- int giXMLTabLevel = -1; // -1 will skip spacing for the outer tag" // ======================================================================= // Helper funcs // ======================================================================= // output opening tag and increment tab level string XMLOpen(string sTag) { string sRet = "<"+sTag+">"; giXMLTabLevel++; int iNumSpaces = (giXMLTabLevel) * TAB_SPACES; string sSpaces = GetStringLeft(BLANK_SPACE_100, iNumSpaces); PrintString(sSpaces + sRet); return sRet; } // decrement tab level, and output closing tag string XMLClose(string sTag) { string sRet = "" + LF; int iNumSpaces = (giXMLTabLevel) * TAB_SPACES; string sSpaces = GetStringLeft(BLANK_SPACE_100, iNumSpaces); PrintString(sSpaces + sRet); giXMLTabLevel--; return sRet; } string ReplaceSpecialChars(string sValue) { int nPostion = FindSubString(sValue,"<"); if (nPostion >= 0) sValue = ""; nPostion = FindSubString(sValue,"&"); if (nPostion >= 0) sValue = ""; return (sValue); } // output all on one line tabbed out 1 additional level string XML(string sTag, string sValue) { sValue = ReplaceSpecialChars(sValue); string sRet = "<"+sTag+">" + sValue + "" + LF; int iNumSpaces = (giXMLTabLevel + 1) * TAB_SPACES; string sSpaces = GetStringLeft(BLANK_SPACE_100, iNumSpaces); PrintString(sSpaces + sRet); return sRet; } // ======================================================================= // ABILITIES // ======================================================================= string GetAbilityName(int iAbility) { string sRet; switch (iAbility) { case ABILITY_STRENGTH: sRet = "Strength"; break; case ABILITY_CONSTITUTION: sRet = "Constitution"; break; case ABILITY_DEXTERITY: sRet = "Dexterity"; break; case ABILITY_INTELLIGENCE: sRet = "Intelligence"; break; case ABILITY_WISDOM: sRet = "Wisdom"; break; case ABILITY_CHARISMA: sRet = "Charisma"; break; } return (sRet); } // Create a single Ability XML output void XMLAbility(object oPC, int iAbility) { XMLOpen(TAG_ABILITY); XML(TAG_ABILITY_NAME, GetAbilityName(iAbility)); XML(TAG_ABILITY_SCORE, IntToString(GetAbilityScore(oPC, iAbility))); XML(TAG_ABILITY_MODIFIER, IntToString(GetAbilityModifier(iAbility, oPC))); XMLClose(TAG_ABILITY); } // Create all Abilities XML output void XMLAbilities(object oPC) { XMLOpen(TAG_ABILITIES); XMLAbility(oPC, ABILITY_STRENGTH); XMLAbility(oPC, ABILITY_CONSTITUTION); XMLAbility(oPC, ABILITY_DEXTERITY); XMLAbility(oPC, ABILITY_INTELLIGENCE); XMLAbility(oPC, ABILITY_WISDOM); XMLAbility(oPC, ABILITY_CHARISMA); XMLClose(TAG_ABILITIES); } // ======================================================================= // ITEMS // ======================================================================= void XMLItemProperty(itemproperty ipItemProperty) { int iPropType = GetItemPropertyType(ipItemProperty); int iPropTypeStrRef = StringToInt(Get2DAString(ITEM_PROPS_2DA, ITEM_PROPS_NAME_COL, iPropType)); string sPropType = GetStringByStrRef(iPropTypeStrRef); XMLOpen(TAG_ITEM_PROPERTY); XML(TAG_ITEM_PROPERTY_TYPE, sPropType); XMLClose(TAG_ITEM_PROPERTY); } void XMLItemProperties(object oItem) { XMLOpen(TAG_ITEM_PROPERTIES); //Get the first itemproperty itemproperty ipLoop=GetFirstItemProperty(oItem); //Loop for as long as the ipLoop variable is valid while (GetIsItemPropertyValid(ipLoop)) { XMLItemProperty(ipLoop); //Next itemproperty on the list... ipLoop=GetNextItemProperty(oItem); } XMLClose(TAG_ITEM_PROPERTIES); } void XMLBaseItemType(object oItem) { int iBIT = GetBaseItemType(oItem); int iBITStrRef = StringToInt(Get2DAString(BIT_2DA, BIT_NAME_COL, iBIT)); string sBITName = GetStringByStrRef(iBITStrRef); XML(TAG_ITEM_TYPE, sBITName); } // Create a single Item XML output void XMLItem(object oItem) { XMLOpen(TAG_ITEM); XML(TAG_ITEM_NAME, GetName(oItem)); //XML(TAG_ITEM_VALUE, IntToString(GetValue(oItem))); XML(TAG_ITEM_WEIGHT, IntToString(GetWeight(oItem))); XML(TAG_ITEM_STACK_SIZE, IntToString(GetItemStackSize(oItem))); XML(TAG_ITEM_AC_VALUE, IntToString(GetItemACValue(oItem))); XML(TAG_ITEM_CHARGES, IntToString(GetItemCharges(oItem))); XMLBaseItemType(oItem); XMLItemProperties(oItem); XMLClose(TAG_ITEM); } // ======================================================================= // EQUIPPED ITEMS // ======================================================================= void XMLEquippedItems(object oPC) { int iSlot; object oInventoryItem; for (iSlot = 0; iSlot < NUM_INVENTORY_SLOTS; iSlot++) { oInventoryItem = GetItemInSlot(iSlot, oPC); if (oInventoryItem != OBJECT_INVALID) XMLItem(oInventoryItem); } } // Create all EQUIPPED ITEMS XML output void XMLEquipment(object oPC) { XMLOpen(TAG_EQUIPPED_ITEMS); XMLEquippedItems(oPC); XMLClose(TAG_EQUIPPED_ITEMS); } // ======================================================================= // INVENTORY ITEMS // ======================================================================= void XMLInventoryItems(object oPC) { object oInventoryItem = GetFirstItemInInventory(oPC); while (oInventoryItem != OBJECT_INVALID) { XMLItem(oInventoryItem); oInventoryItem = GetNextItemInInventory(oPC); } } // Create all INVENTORY XML output void XMLInventory(object oPC) { XMLOpen(TAG_INVENTORY_ITEMS); XMLInventoryItems(oPC); XMLClose(TAG_INVENTORY_ITEMS); } // ======================================================================= // SKILLS // ======================================================================= // Create a single Skill XML output (if creature has the skill) void XMLSkill (int nSkill, object oPC) { int iSkillRank = GetSkillRank(nSkill, oPC); int iBaseSkillRank = GetSkillRank(nSkill, oPC, TRUE); if (GetHasSkill(nSkill, oPC) && (iBaseSkillRank>=0)) { int iSkillName = StringToInt(Get2DAString(SKILLS_2DA, SKILLS_NAME_COL, nSkill)); string sSkillName = GetStringByStrRef(iSkillName); int iSkillDesc = StringToInt(Get2DAString(SKILLS_2DA, SKILLS_DESC_COL, nSkill)); string sSkillDesc = GetStringByStrRef(iSkillDesc); string sTrained; if (iBaseSkillRank == 0) sTrained = TEXT_FALSE; else sTrained = TEXT_TRUE; XMLOpen(TAG_SKILL); XML(TAG_SKILL_NAME, sSkillName); XML(TAG_SKILL_RANK, IntToString(iSkillRank)); XML(TAG_SKILL_RANK_BASE, IntToString(iBaseSkillRank)); XML(TAG_SKILL_TRAINED, sTrained); //XML(TAG_SKILL_DESCRIPTION, sSkillDesc); XMLClose(TAG_SKILL); } } // Create all Skills XML output void XMLSkills(object oPC) { int i; XMLOpen(TAG_SKILLS); for (i=1;i<=SKILLS_ROW_COUNT; i++) XMLSkill(i, oPC); XMLClose(TAG_SKILLS); } // ======================================================================= // FEATS // ======================================================================= // Create a single feat XML output (if creature has the feat) void XMLFeat (int nFeat, object oPC) { if (GetHasFeat(nFeat, oPC, TRUE)) { int iFeatName = StringToInt(Get2DAString(FEATS_2DA, FEATS_NAME_COL, nFeat)); string sFeatName = GetStringByStrRef(iFeatName); int iFeatDescription = StringToInt(Get2DAString(FEATS_2DA, FEATS_DESC_COL, nFeat)); string sFeatDescription = GetStringByStrRef(iFeatDescription); XMLOpen(TAG_FEAT); XML(TAG_FEAT_NAME, sFeatName); //XML(TAG_FEAT_DESCRIPTION, sFeatDescription); XMLClose(TAG_FEAT); } } // Create all Feats XML output void XMLFeats(object oPC) { int i; XMLOpen(TAG_FEATS); for (i=1;i<=FEATS_ROW_COUNT; i++) XMLFeat(i, oPC); XMLClose(TAG_FEATS); } // ======================================================================= // SPELLS // ======================================================================= // // Bard // 1 void XMLSpellClassLevel(int nSpell, int iClass) { string sSpellClassLevel; int iSpellClassLevel = GetSpellLevelForClass(nSpell, iClass); if (iSpellClassLevel >= 0) { int iClassName = StringToInt(Get2DAString(CLASSES_2DA,CLASSES_NAME_COL, iClass)); string sClassName = GetStringByStrRef(iClassName); XMLOpen(TAG_SPELL_CLASS_LEVEL); XML(TAG_SPELL_CLASS, sClassName); XML(TAG_SPELL_LEVEL, IntToString(iSpellClassLevel)); XMLClose(TAG_SPELL_CLASS_LEVEL); } } void XMLSpellLevels(int nSpell, object oPC) { XMLOpen(TAG_SPELL_CLASS_LEVELS); /* XMLSpellClassLevel(nSpell, CLASS_TYPE_BARD); XMLSpellClassLevel(nSpell, CLASS_TYPE_CLERIC); XMLSpellClassLevel(nSpell, CLASS_TYPE_DRUID); XMLSpellClassLevel(nSpell, CLASS_TYPE_PALADIN); XMLSpellClassLevel(nSpell, CLASS_TYPE_RANGER); XMLSpellClassLevel(nSpell, CLASS_TYPE_WIZARD); XMLSpellClassLevel(nSpell, CLASS_TYPE_WARLOCK); */ int i=1; int iClass = GetClassByPosition(i, oPC); while (iClass != CLASS_TYPE_INVALID) { XMLSpellClassLevel(nSpell, iClass); i++; iClass = GetClassByPosition(i, oPC); } XMLClose(TAG_SPELL_CLASS_LEVELS); } // Create a single spell XML output (if creature has the spell memorised) void XMLSpell (int nSpell, object oPC) { int iSpellName = StringToInt(Get2DAString(SPELLS_2DA, SPELLS_NAME_COL, nSpell)); string sSpellName = GetStringByStrRef(iSpellName); int iSpellDesc = StringToInt(Get2DAString(SPELLS_2DA, SPELLS_DESC_COL, nSpell)); string sSpellDesc = GetStringByStrRef(iSpellDesc); string sSpellInnateLevel = Get2DAString(SPELLS_2DA, SPELLS_INNATE_LEVEL_COL, nSpell); XMLOpen(TAG_SPELL); XML(TAG_SPELL_NAME, sSpellName); XML(TAG_SPELL_INNATE_LEVEL, sSpellInnateLevel); XMLSpellLevels(nSpell, oPC); //XML(TAG_SPELL_DESCRIPTION, sSpellDesc); XMLClose(TAG_SPELL); } // Create all Spells XML output void XMLSpellsMemorized(object oPC) { int i; XMLOpen(TAG_SPELLS_MEMORIZED); for (i=1;i<=SPELLS_ROW_COUNT; i++) { if (GetHasSpell(i, oPC)) XMLSpell(i, oPC); } XMLClose(TAG_SPELLS_MEMORIZED); } // ======================================================================= // CLASSES/Levels // ======================================================================= void XMLClass(int iClassPos, object oPC) { int iClass = GetClassByPosition(iClassPos, oPC); int iClassName = StringToInt(Get2DAString(CLASSES_2DA,CLASSES_NAME_COL, iClass)); string sClassName = GetStringByStrRef(iClassName); int iClassLevel = GetLevelByPosition(iClassPos, oPC); XMLOpen(TAG_CLASS); XML(TAG_CLASS_NAME, sClassName); XML(TAG_CLASS_LEVEL, IntToString(iClassLevel)); XMLClose(TAG_CLASS); } void XMLClasses(object oPC) { int i = 1; XMLOpen(TAG_CLASSES); while (GetClassByPosition(i, oPC) != CLASS_TYPE_INVALID) { XMLClass(i, oPC); i++; } XMLClose(TAG_CLASSES); } // ======================================================================= // MISC CHARACTER // ======================================================================= // XML declaration and stylesheet attachment void XMLHeader() { string sRet; PrintString(""); PrintString(""); // return sRet; } void XMLAlignment(object oPC) { XMLOpen(TAG_ALIGNMENT); XML(TAG_ALIGNMENT_LC_CONST, IntToString(GetAlignmentLawChaos(oPC))); XML(TAG_ALIGNMENT_GE_CONST, IntToString(GetAlignmentGoodEvil(oPC))); XMLClose(TAG_ALIGNMENT); } void XMLGender(object oPC) { XML(TAG_GENDER, IntToString(GetGender(oPC))); } void XMLRace(object oPC) { int iRace = GetRacialType(oPC); int iRaceNameStrRef = StringToInt(Get2DAString(RACES_2DA, RACES_NAME_COL, iRace)); string sRaceName = GetStringByStrRef(iRaceNameStrRef); XML(TAG_RACE, sRaceName); } void XMLSaves(object oPC) { XML(TAG_FORT_SAVE, IntToString(GetFortitudeSavingThrow(oPC))); XML(TAG_REFLEX_SAVE, IntToString(GetReflexSavingThrow(oPC))); XML(TAG_WILL_SAVE, IntToString(GetWillSavingThrow(oPC))); } void XMLMiscInfo(object oPC) { XML(TAG_FIRST_NAME, GetFirstName(oPC)); XML(TAG_LAST_NAME, GetLastName(oPC)); XML(TAG_PLAYER_NAME, GetPCPlayerName(oPC)); //XML(TAG_PLAYER_CDKEY, GetPCPublicCDKey(oPC)); XML(TAG_GOLD, IntToString(GetGold(oPC))); XML(TAG_EXPERIENCE, IntToString(GetXP(oPC))); XML(TAG_AGE, IntToString(GetAge(oPC))); XML(TAG_ARMOR_CLASS, IntToString(GetAC(oPC))); XML(TAG_BASE_ATTACK_BONUS, IntToString(GetBaseAttackBonus(oPC))); XML(TAG_HIT_POINTS, IntToString(GetMaxHitPoints(oPC))); XMLGender(oPC); XMLAlignment(oPC); XMLRace(oPC); XMLSaves(oPC); } // ======================================================================= // MAIN // ======================================================================= // script calls iteself so as to avoid const string VAR_LOOP_COUNT = "char_loop_count"; // Use ExecuteScript to run this script on the desired object. // ExecuteScript("ga_character_xml", oTarget)); void main() { // object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oPC = OBJECT_SELF; int iSetupCount = ModifyGlobalInt(VAR_LOOP_COUNT, 1); int bDone = FALSE; switch (iSetupCount) { case 1: PrettyMessage("Export started, please wait..."); PrintString("Save the following as '" + GetName(oPC) + ".xml'"); PrintString("==================================================="); //PrettyMessage(IntToString(iSetupCount) + " - header"); XMLHeader(); XMLOpen(TAG_CHARACTER); break; case 2: //PrettyMessage(IntToString(iSetupCount) + " - abilities, equipment, etc."); XMLMiscInfo(oPC); XMLClasses(oPC); XMLAbilities(oPC); XMLEquipment(oPC); break; case 3: //PrettyMessage(IntToString(iSetupCount) + " - inventory."); XMLInventory(oPC); break; case 4: XMLSkills(oPC); XMLSpellsMemorized(oPC); break; case 5: XMLFeats(oPC); break; case 6: break; default: XMLClose(TAG_CHARACTER); PrintString("==================================================="); bDone = TRUE; PrettyMessage("Character data exported to XML format."); PrettyMessage("Data can be copied from the log to an XML file."); } if (!bDone) { DelayCommand(0.1f, ExecuteScript("gr_character_xml", OBJECT_SELF)); } else { SetGlobalInt(VAR_LOOP_COUNT, 0); // reset for next export. } } // gr_dcr /* Run DetermineCombatRound on self */ #include "nw_i0_generic" void main() { DetermineCombatRound(); } // gr_debug /* Starts the debug conversation for this module This script for use with the dm_runscript console command */ // ChazM 2/24/06 void main() { string sDebugConvo = "00_debug"; AssignCommand(OBJECT_SELF, ActionStartConversation(OBJECT_SELF, sDebugConvo, TRUE, FALSE)); } // gr_dm /* Summons the DM. This script for use with the dm_runscript console command */ // ChazM 11/13/05 #include "x0_i0_position" #include "ginc_debug" void main() { int bValid = GetIsObjectValid(OBJECT_SELF); PrettyDebug("GetIsObjectValid(OBJECT_SELF) returns: " + IntToString(bValid)); location lMyLoc = GetLocation(OBJECT_SELF); PrettyDebug("creating DM at location: " + LocationToString(lMyLoc)); CreateObject(OBJECT_TYPE_CREATURE, "gr_dm", lMyLoc); } // gr_equip_comps.nss // Equip companions with high level gear #include "ginc_debug" const string EQUIP_WEAPON_KHELGAR = "x2_wmdwraxe006"; const string EQUIP_WEAPON_CASAVIR = "x0_wdbmma002"; const string EQUIP_WEAPON_ZHJAEVE = "nw_c3_wblmhw005"; const string EQUIP_WEAPON_GROBNAR = "x0_it_mthnmisc18"; const string EQUIP_WEAPON_ELANEE = "n2_wdbmqs002"; const string EQUIP_WEAPON_SAND = "nw_wmgst003"; const string EQUIP_WEAPON_AMMON = "silver_sword"; const string EQUIP_WEAPON_QARA = "nw_wmgst003"; //const string EQUIP_WEAPON_BISHOP = ""; const string EQUIP_MELEE_ARMS = "nw_it_mbracer010"; const string EQUIP_MELEE_BELT = "x2_it_mbelt002"; const string EQUIP_MELEE_BOOTS = "nw_it_mboots005"; const string EQUIP_MELEE_CHEST = "x0_maarcl023"; const string EQUIP_MELEE_CLOAK = "x0_maarcl040"; const string EQUIP_MELEE_HEAD = "x2_helm_004"; const string EQUIP_MELEE_LRING = "nw_it_mring004"; const string EQUIP_MELEE_NECK = "nw_it_mneck013"; const string EQUIP_MELEE_RRING = "nw_it_mring033"; const string EQUIP_MAGIC_ARMS = "nw_it_mbracer010"; const string EQUIP_MAGIC_BELT = "x2_it_mbelt006"; const string EQUIP_MAGIC_BOOTS = "nw_it_mboots005"; const string EQUIP_MAGIC_CHEST = "n2_mcloth001"; const string EQUIP_MAGIC_CLOAK = "x0_maarcl040"; const string EQUIP_MAGIC_HEAD = "x2_helm_004"; const string EQUIP_MAGIC_LRING = "nw_it_mring004"; const string EQUIP_MAGIC_NECK = "nw_it_mneck013"; const string EQUIP_MAGIC_RRING = "nw_it_mring033"; const string EQUIP_OTHER_ARMS = "nw_it_mbracer010"; const string EQUIP_OTHER_BELT = "x2_it_mbelt006"; const string EQUIP_OTHER_BOOTS = "nw_it_mboots005"; const string EQUIP_OTHER_CHEST = "x0_maarcl006"; const string EQUIP_OTHER_CLOAK = "x0_maarcl040"; const string EQUIP_OTHER_HEAD = "x2_helm_004"; const string EQUIP_OTHER_LRING = "nw_it_mring004"; const string EQUIP_OTHER_NECK = "nw_it_mneck013"; const string EQUIP_OTHER_RRING = "nw_it_mring033"; int GetMeleeLevels( object oCreature ) { return ( GetLevelByClass( CLASS_TYPE_ARCANE_ARCHER, oCreature ) + GetLevelByClass( CLASS_TYPE_BARBARIAN, oCreature ) + GetLevelByClass( CLASS_TYPE_BLACKGUARD, oCreature ) + GetLevelByClass( CLASS_TYPE_CLERIC, oCreature ) + GetLevelByClass( CLASS_TYPE_DIVINECHAMPION, oCreature ) + GetLevelByClass( CLASS_TYPE_DUELIST, oCreature ) + GetLevelByClass( CLASS_TYPE_DWARVENDEFENDER, oCreature ) + GetLevelByClass( CLASS_TYPE_ELDRITCH_KNIGHT, oCreature ) + GetLevelByClass( CLASS_TYPE_FIGHTER, oCreature ) + GetLevelByClass( CLASS_TYPE_FRENZIEDBERSERKER, oCreature ) + GetLevelByClass( CLASS_TYPE_PALADIN, oCreature ) + GetLevelByClass( CLASS_TYPE_WARPRIEST, oCreature ) + GetLevelByClass( CLASS_TYPE_WEAPON_MASTER, oCreature ) ); } int GetMagicLevels( object oCreature ) { return ( GetLevelByClass( CLASS_TYPE_ARCANETRICKSTER, oCreature ) + GetLevelByClass( CLASS_TYPE_DRAGONDISCIPLE, oCreature ) + GetLevelByClass( CLASS_TYPE_PALEMASTER, oCreature ) + GetLevelByClass( CLASS_TYPE_SORCERER, oCreature ) + GetLevelByClass( CLASS_TYPE_WIZARD, oCreature ) ); } int GetOtherLevels( object oCreature ) { return ( GetLevelByClass( CLASS_TYPE_ASSASSIN, oCreature ) + GetLevelByClass( CLASS_TYPE_BARD, oCreature ) + GetLevelByClass( CLASS_TYPE_DRUID, oCreature ) + GetLevelByClass( CLASS_TYPE_HARPER, oCreature ) + GetLevelByClass( CLASS_TYPE_MONK, oCreature ) + GetLevelByClass( CLASS_TYPE_RANGER, oCreature ) + GetLevelByClass( CLASS_TYPE_ROGUE, oCreature ) + GetLevelByClass( CLASS_TYPE_SHADOWDANCER, oCreature ) + GetLevelByClass( CLASS_TYPE_SHADOWTHIEFOFAMN, oCreature ) + GetLevelByClass( CLASS_TYPE_SHAPECHANGER, oCreature ) + GetLevelByClass( CLASS_TYPE_WARLOCK, oCreature ) ); } // unequip all slots void UnequipAll( object oCreature ) { object oItem; int n; for ( n = 0; n <= 15; n++ ) { oItem = GetItemInSlot( n, oCreature ); AssignCommand( oCreature, ActionUnequipItem( oItem ) ); } } void IdentifyAll( object oCreature ) { object oItem = GetFirstItemInInventory( oCreature ); while ( GetIsObjectValid( oItem ) ) { SetIdentified( oItem, TRUE ); oItem = GetNextItemInInventory( oCreature ); } } void EquipMelee( object oCreature ) { UnequipAll( oCreature ); object oArms = CreateItemOnObject( EQUIP_MELEE_ARMS, oCreature, 1 ); object oBelt = CreateItemOnObject( EQUIP_MELEE_BELT, oCreature, 1 ); object oBoots = CreateItemOnObject( EQUIP_MELEE_BOOTS, oCreature, 1 ); object oChest = CreateItemOnObject( EQUIP_MELEE_CHEST, oCreature, 1 ); object oCloak = CreateItemOnObject( EQUIP_MELEE_CLOAK, oCreature, 1 ); object oHead = CreateItemOnObject( EQUIP_MELEE_HEAD, oCreature, 1 ); object oLRing = CreateItemOnObject( EQUIP_MELEE_LRING, oCreature, 1 ); object oNeck = CreateItemOnObject( EQUIP_MELEE_NECK, oCreature, 1 ); object oRRing = CreateItemOnObject( EQUIP_MELEE_RRING, oCreature, 1 ); IdentifyAll( oCreature ); AssignCommand( oCreature, ActionEquipItem( oArms, INVENTORY_SLOT_ARMS ) ); AssignCommand( oCreature, ActionEquipItem( oBelt, INVENTORY_SLOT_BELT ) ); AssignCommand( oCreature, ActionEquipItem( oBoots, INVENTORY_SLOT_BOOTS ) ); AssignCommand( oCreature, ActionEquipItem( oChest, INVENTORY_SLOT_CHEST ) ); AssignCommand( oCreature, ActionEquipItem( oCloak, INVENTORY_SLOT_CLOAK ) ); AssignCommand( oCreature, ActionEquipItem( oHead, INVENTORY_SLOT_HEAD ) ); AssignCommand( oCreature, ActionEquipItem( oLRing, INVENTORY_SLOT_LEFTRING ) ); AssignCommand( oCreature, ActionEquipItem( oNeck, INVENTORY_SLOT_NECK ) ); AssignCommand( oCreature, ActionEquipItem( oRRing, INVENTORY_SLOT_RIGHTRING ) ); } void EquipMagic( object oCreature ) { UnequipAll( oCreature ); object oArms = CreateItemOnObject( EQUIP_MAGIC_ARMS, oCreature, 1 ); object oBelt = CreateItemOnObject( EQUIP_MAGIC_BELT, oCreature, 1 ); object oBoots = CreateItemOnObject( EQUIP_MAGIC_BOOTS, oCreature, 1 ); object oChest = CreateItemOnObject( EQUIP_MAGIC_CHEST, oCreature, 1 ); object oCloak = CreateItemOnObject( EQUIP_MAGIC_CLOAK, oCreature, 1 ); object oHead = CreateItemOnObject( EQUIP_MAGIC_HEAD, oCreature, 1 ); object oLRing = CreateItemOnObject( EQUIP_MAGIC_LRING, oCreature, 1 ); object oNeck = CreateItemOnObject( EQUIP_MAGIC_NECK, oCreature, 1 ); object oRRing = CreateItemOnObject( EQUIP_MAGIC_RRING, oCreature, 1 ); IdentifyAll( oCreature ); AssignCommand( oCreature, ActionEquipItem( oArms, INVENTORY_SLOT_ARMS ) ); AssignCommand( oCreature, ActionEquipItem( oBelt, INVENTORY_SLOT_BELT ) ); AssignCommand( oCreature, ActionEquipItem( oBoots, INVENTORY_SLOT_BOOTS ) ); AssignCommand( oCreature, ActionEquipItem( oChest, INVENTORY_SLOT_CHEST ) ); AssignCommand( oCreature, ActionEquipItem( oCloak, INVENTORY_SLOT_CLOAK ) ); AssignCommand( oCreature, ActionEquipItem( oHead, INVENTORY_SLOT_HEAD ) ); AssignCommand( oCreature, ActionEquipItem( oLRing, INVENTORY_SLOT_LEFTRING ) ); AssignCommand( oCreature, ActionEquipItem( oNeck, INVENTORY_SLOT_NECK ) ); AssignCommand( oCreature, ActionEquipItem( oRRing, INVENTORY_SLOT_RIGHTRING ) ); } void EquipOther( object oCreature ) { UnequipAll( oCreature ); object oArms = CreateItemOnObject( EQUIP_OTHER_ARMS, oCreature, 1 ); object oBelt = CreateItemOnObject( EQUIP_OTHER_BELT, oCreature, 1 ); object oBoots = CreateItemOnObject( EQUIP_OTHER_BOOTS, oCreature, 1 ); object oChest = CreateItemOnObject( EQUIP_OTHER_CHEST, oCreature, 1 ); object oCloak = CreateItemOnObject( EQUIP_OTHER_CLOAK, oCreature, 1 ); object oHead = CreateItemOnObject( EQUIP_OTHER_HEAD, oCreature, 1 ); object oLRing = CreateItemOnObject( EQUIP_OTHER_LRING, oCreature, 1 ); object oNeck = CreateItemOnObject( EQUIP_OTHER_NECK, oCreature, 1 ); object oRRing = CreateItemOnObject( EQUIP_OTHER_RRING, oCreature, 1 ); IdentifyAll( oCreature ); AssignCommand( oCreature, ActionEquipItem( oArms, INVENTORY_SLOT_ARMS ) ); AssignCommand( oCreature, ActionEquipItem( oBelt, INVENTORY_SLOT_BELT ) ); AssignCommand( oCreature, ActionEquipItem( oBoots, INVENTORY_SLOT_BOOTS ) ); AssignCommand( oCreature, ActionEquipItem( oChest, INVENTORY_SLOT_CHEST ) ); AssignCommand( oCreature, ActionEquipItem( oCloak, INVENTORY_SLOT_CLOAK ) ); AssignCommand( oCreature, ActionEquipItem( oHead, INVENTORY_SLOT_HEAD ) ); AssignCommand( oCreature, ActionEquipItem( oLRing, INVENTORY_SLOT_LEFTRING ) ); AssignCommand( oCreature, ActionEquipItem( oNeck, INVENTORY_SLOT_NECK ) ); AssignCommand( oCreature, ActionEquipItem( oRRing, INVENTORY_SLOT_RIGHTRING ) ); } void EquipWeapon( object oCompanion ) { string sTag = GetTag( oCompanion ); object oWeapon; if ( sTag == "ammon_jerro" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_AMMON, oCompanion, 1 ); } else if ( sTag == "bishop" ) { //oWeapon = CreateItemOnObject( EQUIP_WEAPON_BISHOP, oCompanion, 1 ); } else if ( sTag == "casavir" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_CASAVIR, oCompanion, 1 ); } else if ( sTag == "khelgar" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_KHELGAR, oCompanion, 1 ); } else if ( sTag == "grobnar" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_GROBNAR, oCompanion, 1 ); } else if ( sTag == "elanee" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_ELANEE, oCompanion, 1 ); } else if ( sTag == "qara" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_QARA, oCompanion, 1 ); } else if ( sTag == "sand" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_SAND, oCompanion, 1 ); } else if ( sTag == "zhjaeve" ) { oWeapon = CreateItemOnObject( EQUIP_WEAPON_ZHJAEVE, oCompanion, 1 ); } SetIdentified( oWeapon, TRUE ); AssignCommand( oCompanion, ActionEquipItem( oWeapon, INVENTORY_SLOT_RIGHTHAND ) ); } void Equip( object oCreature ) { int nClass = 0; int nMelee = GetMeleeLevels( oCreature ); int nMagic = GetMagicLevels( oCreature ); int nOther = GetOtherLevels( oCreature ); if ( ( nMagic > nMelee ) && ( nMagic > nOther ) ) { nClass = 1; } if ( ( nOther > nMelee ) && ( nOther > nMagic ) ) { nClass = 2; } switch ( nClass ) { case 0: EquipMelee( oCreature ); break; case 1: EquipMagic( oCreature ); break; case 2: EquipOther( oCreature ); break; } EquipWeapon( oCreature ); } void main() { PrettyDebug( "gr_equip_comps: equiping companions with high level gear" ); object oPC = GetFirstPC(); object oFM = GetFirstFactionMember( oPC, FALSE ); while ( GetIsObjectValid(oFM) ) { // Give all roster members in party some equipment if ( GetIsRosterMember(oFM) == TRUE ) { Equip( oFM ); } oFM = GetNextFactionMember( oPC, FALSE ); } } // gr_followleader /* Sets player to auto-follow the party leader. This script for use with the dm_runscript console command */ // ChazM 11/6/05 void main() { object oLeader = GetFactionLeader(OBJECT_SELF); if (GetIsObjectValid(oLeader) == TRUE) { AssignCommand(OBJECT_SELF, ActionForceFollowObject(oLeader, 3.0f)); } } // gr_followpos /* test script for setting up follow positions */ // ChazM 8/9/06 #include "ginc_debug" #include "ginc_companion" void main() { object oPC = GetFirstPC(); object oWho = GetFactionLeader(oPC); object oMember = GetFirstFactionMember( oPC, FALSE ); int i = 0; float fFollowDistance; PrettyDebug("Everyone follow " + GetName(oWho) + "!"); while ( GetIsObjectValid( oMember ) == TRUE ) { AssignCommand(oMember, ClearAllActions()); PrettyDebug(GetName(oMember) + " Follow Position = " + IntToString(i) ); SetLocalInt(oMember, "FollowPos", i); // this will by the default AI, but not in gb_comp_heart yet. fFollowDistance = GetFollowDistance(oMember); AssignCommand(oMember, ActionForceFollowObject(oWho, fFollowDistance, i)); i++; oMember = GetNextFactionMember( oPC, FALSE ); } } // gr_henchinv /* open inventory of henchman 1. This script for use with the dm_runscript console command */ // ChazM 11/13/05 void main() { OpenInventory(GetHenchman(), OBJECT_SELF); } //gr_input_test #include "ginc_crafting" void main() { object oPC = OBJECT_SELF; object oItem = GetFirstItemInInventory(oPC); SpeakString("about to rename item: " + GetName(oItem)); SetEnchantedItemName(oPC, oItem); // DisplayInputBox( OBJECT_SELF, 0, "Test Message", "gui_input_ok", "", 1, // "SCREEN_STRINGINPUT_MESSAGEBOX", 0, "OKAY", 0, "CANCEL", "DefaultSTR", "VariableSTring" ); } // gr_instrument /* Gives player the instrument of death. This script for use with the dm_runscript console command */ // ChazM 11/23/05 void AddSuperSpellItemProp(object oItem, int iSpell) { itemproperty ipAdd = ItemPropertyCastSpell(iSpell, IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE); AddItemProperty(DURATION_TYPE_PERMANENT, ipAdd, oItem); } // create an item and add super abilities to it. void MakeInstrument() { object oItem = CreateItemOnObject("nw_it_novel002"); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_POWER_WORD_KILL_17); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_WEIRD_17); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_DOMINATE_MONSTER_17); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_METEOR_SWARM_17); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_SUMMON_CREATURE_IX_17); AddSuperSpellItemProp(oItem, IP_CONST_CASTSPELL_WAIL_OF_THE_BANSHEE_17); } void main() { object oItem = CreateItemOnObject("instodeath"); //MakeInstrument(); } // gr_item_report /* */ // ChazM 10/26/06 #include "ginc_debug" void main() { object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker()); object oItem = GetFirstItemInInventory(oPC); string sOut = "First item in inventory: " + GetName(oItem) + " tag: " + GetTag(oItem) + " ResRef: " + GetResRef(oItem); PrettyDebug(sOut); AssignCommand(oPC, SpeakString(sOut)); } // gr_jumpleader /* Teleports player to the party leader. This script for use with the dm_runscript console command */ // ChazM 11/6/05 void main() { object oLeader = GetFactionLeader(OBJECT_SELF); if (GetIsObjectValid(oLeader) == TRUE) { AssignCommand(OBJECT_SELF, JumpToObject(oLeader)); } } // gr_jumptodm /* jumpts player to the a DM. This script for use with the dm_runscript console command */ // ChazM 11/13/05 void main() { object oDM = GetObjectByTag("gr_dm"); if (GetIsObjectValid(oDM) == TRUE) { AssignCommand(OBJECT_SELF, JumpToObject(oDM)); } } // gr_kill_aoe( float fRadius ) // Inflict massive damage to hostiles within fRadius meters // BMA-OEI 8/30/06 #include "ginc_debug" const float KILL_AOE_MIN_RADIUS = 9.0f; const int KILL_AOE_MASSIVE_DAMAGE = 9999; void main( float fRadius ) { if ( fRadius < 0.1f ) { fRadius = KILL_AOE_MIN_RADIUS; } object oKiller = OBJECT_SELF; location lKiller = GetLocation( OBJECT_SELF ); effect eKill = EffectDamage( KILL_AOE_MASSIVE_DAMAGE ); object oTarget = GetFirstObjectInShape( SHAPE_SPHERE, fRadius, lKiller, TRUE, OBJECT_TYPE_CREATURE ); PrettyDebug( "gr_kill_aoe: searching for creatures hostile to " + GetName(oKiller) + " within " + FloatToString(fRadius) + " meters" ); while ( GetIsObjectValid( oTarget ) == TRUE ) { if ( ( GetIsDead( oTarget ) == FALSE ) && ( GetIsEnemy( oTarget ) == TRUE ) ) { DelayCommand( 0.1f, ApplyEffectToObject( DURATION_TYPE_INSTANT, eKill, oTarget ) ); PrettyMessage( "gr_kill_aoe: ** applying " + IntToString(KILL_AOE_MASSIVE_DAMAGE) + " damage to " + GetName(oTarget) ); } oTarget = GetNextObjectInShape( SHAPE_SPHERE, fRadius, lKiller, TRUE, OBJECT_TYPE_CREATURE ); } } // gr_lostitems /* Opens up the LostItems store for the player. If no lost items store is found, one is created. Plot items aren't added to this store if it doesn't exist, so this command be run once at the beginning of the module to make sure one is created. This script for use with the dm_runscript console command */ // ChazM 11/6/05 const string TAG_LOST_ITEMS = "LostItems"; const string RR_LOST_ITEMS = "nw_lostitems"; void main() { object oStore = GetObjectByTag(TAG_LOST_ITEMS); if (!GetIsObjectValid(oStore)) { PrintString ("Creating Lost Items store"); oStore = CreateObject(OBJECT_TYPE_STORE, RR_LOST_ITEMS, GetLocation(OBJECT_SELF)); SetStoreMaxBuyPrice(oStore, 0); } OpenStore(oStore, OBJECT_SELF, -100); } // gr_outofmyway.nss /* Force nearby creatures to move away from the PC. */ // BMA-OEI 5/02/06 #include "ginc_debug" const int MAX_CREATURES = 10; const float MAX_DISTANCE = 5.0f; void main() { location lTarget = GetLocation( OBJECT_SELF ); effect eVis = EffectVisualEffect( 535 ); ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eVis, OBJECT_SELF, 3.0f ); int nCount = 1; object oCreature = GetNearestCreature( CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE, OBJECT_SELF, nCount ); while ( ( GetIsObjectValid( oCreature ) == TRUE ) && ( nCount < MAX_CREATURES ) ) { if ( GetDistanceBetween( oCreature, OBJECT_SELF ) < MAX_DISTANCE ) { PrettyMessage( "gr_outofmyway: attempting to move " + GetName( oCreature ) + " away from " + GetName( OBJECT_SELF ) ); AssignCommand( oCreature, ClearAllActions() ); AssignCommand( oCreature, ActionMoveAwayFromLocation( lTarget, FALSE, MAX_DISTANCE ) ); } nCount = nCount + 1; oCreature = GetNearestCreature( CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE, OBJECT_SELF, nCount ); } } // gr_pc_spawn /* the spawn-like script for PC's Sets up listening patterns and variables. */ // ChazM 9/13/06 // ChazM 9/14/06 Added Set DoneSpawn // ChazM 9/20/06 - fixed inc. // DBR 9/21/06 - Added a class check before setting the 'Open Lock' and 'Disable Trap' behavior. #include "x0_inc_henai" #include "ginc_math" // this is run on the PC, so OBJECT_SELF != module for this funciton. void main() { PrettyDebug(GetName(OBJECT_SELF) + ": PC Spawn script run!"); // Always set up listening patterns // Sets up the special henchmen listening patterns (gb_setassociatelistenpatterns) SetAssociateListenPatterns(); // Set standard combat listening patterns (x0_i0_spawncond) SetListeningPatterns(); // Set additional henchman listening patterns (x0_inc_henai) bkSetListeningPatterns(); // Only set up variables if we haven't done this before. int iDoneSpawn = GetLocalInt(OBJECT_SELF, "DoneSpawn"); if (iDoneSpawn) return; SetLocalInt(OBJECT_SELF, "DoneSpawn", TRUE); // Default behavior for henchmen at start SetAssociateState(NW_ASC_SCALED_CASTING); SetAssociateState(NW_ASC_HEAL_AT_50); if (GetLevelByClass(CLASS_TYPE_ROGUE) > 0) { SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS); SetAssociateState(NW_ASC_DISARM_TRAPS); } // PC's won't use items by default when not controlled. // This way they have someplace to put their scrolls and potions w/o them dissappearing. SetLocalIntState(OBJECT_SELF, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ITEM, TRUE); // * July 2003. Set this to true so henchmen // * will hopefully run off a little less often // * by default // * September 2003. Bad decision. Reverted back // * to original. This mode too often looks like a bug // * because they hang back and don't help each other out. // Players (like companions) defaulted to Defend. SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, TRUE); SetAssociateState(NW_ASC_DISTANCE_2_METERS); // Use melee weapons by default SetAssociateState(NW_ASC_USE_RANGED_WEAPON, FALSE); // Set starting location //SetAssociateStartLocation(); // Set respawn location //SetRespawnLocation(); // For some general behavior while we don't have a master, // let's do some immobile animations SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS); } // gr_print_effects( string sTag ) // BMA-OEI 9/05/06 #include "ginc_debug" #include "ginc_param_const" void PrintEffect( effect eEffect ); void PrintEffectsOnObject( object oObject ); void main( string sTag ) { object oObject = GetTarget( sTag ); PrettyDebug( "gr_print_effects: printing effects on " + GetName( oObject ) + " (Tag:" + GetTag( oObject ) + ")" ); PrintEffectsOnObject( oObject ); } void PrintEffect( effect eEffect ) { PrettyMessage( " ** Creator : " + GetName( GetEffectCreator( eEffect ) ) + " (Tag:" + GetTag( GetEffectCreator( eEffect ) ) + ")" ); PrettyMessage( " ** Duration: " + IntToString( GetEffectDurationType( eEffect ) ) ); PrettyMessage( " ** SpellId : " + IntToString( GetEffectSpellId( eEffect ) ) ); PrettyMessage( " ** Type : " + IntToString( GetEffectType( eEffect ) ) ); PrettyMessage( " ** SubType : " + IntToString( GetEffectSubType( eEffect ) ) ); } void PrintEffectsOnObject( object oObject ) { string sName = GetName( oObject ); string sTag = GetTag( oObject ); effect eEffect = GetFirstEffect( oObject ); int n = 1; while ( GetIsEffectValid( eEffect ) == TRUE ) { PrettyDebug( "Effect #" + IntToString( n ) + " on " + sName + " (Tag:" + sTag + ")" ); PrintEffect( eEffect ); n = n + 1; eEffect = GetNextEffect( oObject ); } } //gr_report /* info on target */ //ChazM 6/28/06 // ChazM 8/23/06 - added hitpoints // BMA-OEI 8/30/06 - added plotflag, immortal #include "ginc_param_const" #include "x0_i0_position" #include "ginc_event_handlers" void main(string sTarget) { object oTarget = GetTarget(sTarget); PrettyDebug("----------- Report ------------------"); PrettyDebug("Target Name: " + GetName(oTarget)); PrettyDebug(" Hit Points: " + IntToString(GetCurrentHitPoints(oTarget)) + " of " + IntToString(GetMaxHitPoints(oTarget)) ); PrettyDebug(" Commandable = " + IntToString(GetCommandable(oTarget))); PrettyDebug(" PossessionBlocked = " + IntToString( GetIsCompanionPossessionBlocked(oTarget) ) ); //PrettyDebug(" Destroyable = Who knows?"); PrettyDebug(" Plot Flag = " + IntToString(GetPlotFlag(oTarget))); PrettyDebug(" Immortal = " + IntToString(GetImmortal(oTarget))); PrettyDebug(GetName(oTarget) + " is currently in:"); PrettyDebug(" Module: " + GetName(GetModule()) + " / Module Tag: " + GetTag(GetModule()) ); PrettyDebug(" Area Name: " + GetName(GetArea(oTarget)) + " / Area Tag: " + GetTag(GetArea(oTarget)) ); PrettyDebug(" Position: " + VectorToString(GetPosition(oTarget)) ); PrettyDebug(" Facing: " + FloatToString(GetFacing(oTarget)) ); ReportEventHandlers(oTarget); PrettyDebug("----------- End Report --------------"); } #include "ginc_death" #include "ginc_debug" void main() { object oPC = OBJECT_SELF; PrettyDebug( "gr_respawn: DEBUG - resurrecting " + GetName(oPC) + "'s faction" ); ResurrectFaction( oPC ); } // gr_restart /* Restarts the module. Assumes module name is the file name. This script for use with the dm_runscript console command */ // ChazM 11/6/05 void main() { string sModuleName = GetName(GetModule()); StartNewModule(sModuleName); } // gr_roster_reset // Resets all roster members in-game to average PC level #include "ginc_debug" #include "ginc_misc" void main() { int nXP = GetPCAverageXP(); string sRM = GetFirstRosterMember(); object oRM; while ( sRM != "" ) { oRM = GetObjectFromRosterName( sRM ); if ( GetIsObjectValid( oRM ) == TRUE ) { PrettyMessage( "gr_roster_reset: " + GetName( oRM ) + " reset with " + IntToString( nXP ) + " xp." ); ResetCreatureLevelForXP( oRM, nXP, TRUE ); ForceRest( oRM ); } sRM = GetNextRosterMember(); } } // DEBUG SCRIPT - REPORT TAGS // DBR //#include "ginc_debug" void TRIterate(location lOrigin, int i) { if (i>27) return; object oObj=GetNearestObjectToLocation(OBJECT_TYPE_ALL,lOrigin,++i); while ((GetTag(oObj)=="blergblerg")||(GetObjectType(oObj)==OBJECT_TYPE_CREATURE)) oObj=GetNearestObjectToLocation(OBJECT_TYPE_ALL,lOrigin,++i); if (!GetIsObjectValid(oObj)) return; //PrettyMessage("-"+GetTag(oObj)); //object oYeller = CreateObject(OBJECT_TYPE_CREATURE,"n_duncan",GetLocation(oObj),FALSE,"blergblerg"); //SetScriptHidden(oYeller,TRUE); AssignCommand(OBJECT_SELF,SpeakString(GetTag(oObj),TALKVOLUME_SHOUT)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectNWN2SpecialEffectFile("sp_fire_hit"),oObj,1.2f); //DelayCommand(7.0f,DestroyObject(oYeller)); DelayCommand(1.0f,TRIterate(lOrigin,i+1)); } void main() { int i=0; AssignCommand(OBJECT_SELF,TRIterate(GetLocation(OBJECT_SELF),0)); object oC=GetNearestObject(OBJECT_TYPE_CREATURE,OBJECT_SELF,++i); while (GetIsObjectValid(oC)) { AssignCommand(oC,SpeakString(GetTag(oC))); oC=GetNearestObject(OBJECT_TYPE_CREATURE,OBJECT_SELF,++i); } } // gr_where_am_i /* Reports current location This script for use with the dm_runscript console command */ // ChazM 11/13/05 #include "ginc_debug" #include "x0_i0_position" // dfdsa void main() { PrettyDebug(GetName(OBJECT_SELF) + " is currently in:"); PrettyDebug(" Module: " + GetName(GetModule()) + " / Module Tag: " + GetTag(GetModule()) ); PrettyDebug(" Area Name: " + GetName(GetArea(OBJECT_SELF)) + " / Area Tag: " + GetTag(GetArea(OBJECT_SELF)) ); PrettyDebug(" Position: " + VectorToString(GetPosition(OBJECT_SELF)) ); PrettyDebug(" Facing: " + FloatToString(GetFacing(OBJECT_SELF)) ); } Global Trigger // gtr_block_trigger /* Used on enter of a trigger to block the player from entering and jump them to a nearby waypoint. Note that conversations should consist of one-line barkstrings only. */ // Tevans 1/24/06 - Created script and trigger #include "ginc_debug" #include "ginc_param_const" void main () { object oEntering = GetEnteringObject(); if ( !GetIsPC(oEntering) ) // if the entering object is not a PC, bail out return; // Get the trigger's local variables string sWP = GetLocalString( OBJECT_SELF, "Waypoint" ); string sVar = GetLocalString( OBJECT_SELF, "Variable" ); string sConv = GetLocalString( OBJECT_SELF, "Conversation" ); string sSpeaker = GetLocalString( OBJECT_SELF, "Speaker" ); int bBarkstring = GetLocalInt( OBJECT_SELF, "PlayBarkstring" ); if ( !GetGlobalInt(sVar) ) { // The global flag for prohibiting entry into the trigger is off; bail out PrettyError( "Variable " + sVar + " is FALSE" ); return; } object oWP = GetTarget( sWP ); if ( !GetIsObjectValid(oWP) ) { // The provided waypoint tag doesn't match a valid object; bail out PrettyError( "Waypoint " + sWP + " is INVALID" ); return; } AssignCommand( oEntering, FadeToBlack(OBJECT_SELF, FADE_SPEED_FASTEST) ); AssignCommand( oEntering, ClearAllActions() ); DelayCommand( FADE_SPEED_FASTEST / 3.0f, AssignCommand(oEntering, JumpToObject( oWP )) ); DelayCommand( FADE_SPEED_FASTEST * 1.5f, AssignCommand(oEntering, FadeFromBlack( OBJECT_SELF )) ); if ( sSpeaker == "" && bBarkstring) { AssignCommand( oEntering, SpeakStringByStrRef(113518) ); // see dialog.tlk for entry 113518 } else if (sSpeaker == "" && sConv == "") return; else { int bPrivateConversation = FALSE; int bPlayHello = FALSE; int bIgnoreStartDistance = TRUE; int bDisableCutsceneBars = FALSE; object oSpeaker = GetTarget( sSpeaker ); if ( !GetIsObjectValid(oSpeaker) ) { PrettyError( "Speaker " + sSpeaker + " is INVALID. Using PC" ); oSpeaker = oEntering; } AssignCommand( oSpeaker, ActionStartConversation(oEntering, sConv, bPrivateConversation, bPlayHello, bIgnoreStartDistance, bDisableCutsceneBars) ); } } // gtr_murder_en // // Kills creature with tag "sCreatureToMurder" when PC steps on this. // // EPF 7/12/05 #include "ginc_misc" void main() { string sCreatureToMurder = GetLocalString(OBJECT_SELF, "sCreatureToMurder"); object oCreatureToMurder = GetTarget(sCreatureToMurder); PrintString("Murder trigger: Murdering " + GetTag(oCreatureToMurder)); if(GetIsObjectValid(oCreatureToMurder)) { //leave the corpse AssignCommand(oCreatureToMurder, SetIsDestroyable(FALSE,FALSE,TRUE)); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oCreatureToMurder); } } //:://///////////////////////////////////////////////////////////////////////// //:: //:: gtr_pc_tran_clic.nss //:: //:: Use this script as a trigger's OnClick event handler to ensure that the //:: trigger is only tripped by a PC. This is the default OnClick handler for //:: the global PC-Only Area Transition Trigger. //:: //:://///////////////////////////////////////////////////////////////////////// //:: //:: Created by: Brian Fox //:: Created on: 8/19/05 //:: //:://///////////////////////////////////////////////////////////////////////// // BMA-OEI 6/24/06 - Change to use AttemptAreaTransition() #include "ginc_transition" void main() { object oClicker = GetClickingObject(); if ( GetIsPC( oClicker ) == FALSE ) return; object oTarget = GetTransitionTarget( OBJECT_SELF ); SetAreaTransitionBMP( AREA_TRANSITION_RANDOM ); AttemptAreaTransition( oClicker, oTarget ); } // gtr_speak_node /* Speak Trigger OnEnter handler to initiate a conversation. See DoSpeakTrigger() in ginc_trigger for list of variables that can be set. For custom conditions, modify , save as a new script and attach to trigger's OnEnter. Suggested name: XX_trsn_xxx */ // ChazM 6/25/05 - split functions into include // BMA-OEI 3/6/06 - formated script #include "ginc_trigger" void main () { object oPC = GetEnteringObject(); if (StandardSpeakTriggerConditions(oPC) == FALSE) { return; } //if ( == FALSE) //{ // return; //} DoSpeakTrigger(oPC); } Graphical User Interace // gui_bhvr_a_casting_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_CASTING_OFF); } // gui_bhvr_a_casting_overkill /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_CASTING_OVERKILL); } // gui_bhvr_a_casting_power /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_CASTING_POWER); } // gui_bhvr_a_casting_scaled /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_CASTING_SCALED); } // gui_bhvr_a_combat_mode_use_off.nss /* Combat Mode Use All Off Behavior script for the character sheet behavior sub-panel */ // BMA-OEI 10/12/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll( STR_REF_BEHAVIOR_COMBAT_MODE_USE_OFF ); } // gui_bhvr_a_combat_mode_use_on.nss /* Combat Mode Use All On Behavior script for the character sheet behavior sub-panel */ // BMA-OEI 10/12/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll( STR_REF_BEHAVIOR_COMBAT_MODE_USE_ON ); } // gui_bhvr_a_def_master_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DEF_MASTER_OFF); } // gui_bhvr_a_def_master_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DEF_MASTER_ON); } // gui_bhvr_a_disarm_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DISARM_TRAPS_OFF); } // gui_bhvr_a_disarm_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DISARM_TRAPS_ON); } // gui_bhvr_a_dispel_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DISPEL_OFF); } // gui_bhvr_a_dispel_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_DISPEL_ON); } // gui_bhvr_a_feat_use_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/8/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_FEAT_USE_OFF); } // gui_bhvr_a_feat_use_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/8/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_FEAT_USE_ON); } // gui_bhvr_a_follownear.nss /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_FOLLOWDIST_FAR); } // gui_bhvr_a_follownear.nss /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_FOLLOWDIST_MED); } // gui_bhvr_a_follownear.nss /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_FOLLOWDIST_NEAR); } // gui_bhvr_a_item_use_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/7/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_ITEM_USE_OFF); } // gui_bhvr_a_item_use_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/7/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_ITEM_USE_ON); } // gui_bhvr_a_puppet_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/9/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_PUPPET_OFF); } // gui_bhvr_a_puppet_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/9/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_PUPPET_ON); } // gui_bhvr_a_retry_locks_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_RETRY_LOCKS_OFF); } // gui_bhvr_a_retry_locks_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_RETRY_LOCKS_ON); } // gui_bhvr_a_stealth_none /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_STEALTH_MODE_NONE); } // gui_bhvr_a_stealth_perm /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_STEALTH_MODE_PERM); } // gui_bhvr_a_stealth_temp /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/4/06 #include "gui_bhvr_inc" void main() { SetBehaviorAll(STR_REF_BEHAVIOR_STEALTH_MODE_TEMP); } // gui_bhvr_casting_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_CASTING_OFF, iExamined); } // gui_bhvr_casting_overkill /* Behavior script for the character sheet behavior sub-panel */ // ChazM 7/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_CASTING_OVERKILL, iExamined); } // gui_bhvr_casting_power /* Behavior script for the character sheet behavior sub-panel */ // ChazM 7/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_CASTING_POWER, iExamined); } // gui_bhvr_casting_scaled /* Behavior script for the character sheet behavior sub-panel */ // ChazM 7/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_CASTING_SCALED, iExamined); } // gui_bhvr_combat_mode_use_off.nss /* Combat Mode Use Off Behavior script for the character sheet behavior sub-panel */ // BMA-OEI 10/12/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_COMBAT_MODE_USE_OFF, iExamined); } // gui_bhvr_combat_mode_use_on.nss /* Combat Mode Use On Behavior script for the character sheet behavior sub-panel */ // BMA-OEI 10/12/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_COMBAT_MODE_USE_ON, iExamined); } // gui_bhvr_def_master_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DEF_MASTER_OFF, iExamined); } // gui_bhvr_def_master_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DEF_MASTER_ON, iExamined); } // gui_bhvr_disarm_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DISARM_TRAPS_OFF, iExamined); } // gui_bhvr_disarm_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DISARM_TRAPS_ON, iExamined); } // gui_bhvr_dispel_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DISPEL_OFF, iExamined); } // gui_bhvr_dispel_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_DISPEL_ON, iExamined); } // gui_bhvr_feat_use_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/8/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_FEAT_USE_OFF, iExamined); } // gui_bhvr_feat_use_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/8/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_FEAT_USE_ON, iExamined); } //:://///////////////////////////////////////////// //:: Behavior Screen - Follow Distance: Far //:: gui_bhvr_followfar.nss //:: Created By: Brock Heinz - OEI //:: Created On: 03/29/06 //::////////////////////////////////////////////// // ChazM 4/26/06 - use SetBehavior() // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_FOLLOWDIST_FAR, iExamined); } //:://///////////////////////////////////////////// //:: Behavior Screen - Follow Distance: Medium //:: gui_bhvr_followmed.nss //:: Created By: Brock Heinz - OEI //:: Created On: 03/29/06 //::////////////////////////////////////////////// // ChazM 4/26/06 - use SetBehavior() // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_FOLLOWDIST_MED, iExamined); } //:://///////////////////////////////////////////// //:: Behavior Screen - Follow Distance: Near //:: gui_bhvr_follownear.nss //:: Created By: Brock Heinz - OEI //:: Created On: 03/29/06 //::////////////////////////////////////////////// // ChazM 4/26/06 - use SetBehavior() // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_FOLLOWDIST_NEAR, iExamined); } // gui_bhvr_inc /* include file for the GUI Behavior related scripts: gui_bhvr_follownear gui_bhvr_followmed gui_bhvr_followfar gui_bhvr_def_master_on gui_bhvr_def_master_off gui_bhvr_retry_locks_on gui_bhvr_retry_locks_off gui_bhvr_stealth_none gui_bhvr_stealth_perm gui_bhvr_stealth_temp gui_bhvr_disarm_on gui_bhvr_disarm_off gui_bhvr_dispel_on gui_bhvr_dispel_off gui_bhvr_casting_overkill gui_bhvr_casting_power gui_bhvr_casting_scaled gui_bhvr_casting_off gui_bhvr_item_use_on gui_bhvr_item_use_off gui_bhvr_feat_use_on gui_bhvr_feat_use_off gui_bhvr_combat_mode_use_on gui_bhvr_combat_mod_use_off gui_bhvr_a_follownear gui_bhvr_a_followmed gui_bhvr_a_followfar gui_bhvr_a_def_master_on gui_bhvr_a_def_master_off gui_bhvr_a_retry_locks_on gui_bhvr_a_retry_locks_off gui_bhvr_a_stealth_none gui_bhvr_a_stealth_perm gui_bhvr_a_stealth_temp gui_bhvr_a_disarm_on gui_bhvr_a_disarm_off gui_bhvr_a_dispel_on gui_bhvr_a_dispel_off gui_bhvr_a_casting_overkill gui_bhvr_a_casting_power gui_bhvr_a_casting_scaled gui_bhvr_a_casting_off gui_bhvr_a_item_use_on gui_bhvr_a_item_use_off gui_bhvr_a_feat_use_on gui_bhvr_a_feat_use_off gui_bhvr_a_combat_mode_use_on gui_bhvr_a_combat_mod_use_off */ // ChazM 4/26/06 // ChazM 5/25/06 - script now runs on player owned character - functions modified to reference currently controlled character // ChazM 5/26/06 - removed debugs // ChazM 7/26/06 - Added casting_overkill, casting_power, casting_scaled, removed casting_on // ChazM 8/4/06 - Added support for full party controls (all buttons) // ChazM 8/7/06 - Added support for item use // ChazM 8/8/06 - Added support for ability/feat use // ChazM 8/9/06 - Added support for puppet mode // BMA-OEI 10/12/06 - Added support for combat mode use (N2_COMBAT_MODE_USE_DISABLED) // ChazM 11/9/06 - Examined Creature update //void main(){} #include "x0_i0_assoc" #include "ginc_debug" #include "x0_i0_talent" #include "ginc_math" const string SCREEN_CHARACTER = "SCREEN_CHARACTER"; const string SCREEN_CREATUREEXAMINE = "SCREEN_CREATUREEXAMINE"; const string BEHAVIORDESC_TEXT = "BEHAVIORDESC_TEXT"; const string BEHAVIOR_FOLLOWDIST_NEAR = "BEHAVIOR_FOLLOWDIST_STATE_BUTTON_NEAR"; const string BEHAVIOR_FOLLOWDIST_MED = "BEHAVIOR_FOLLOWDIST_STATE_BUTTON_MED"; const string BEHAVIOR_FOLLOWDIST_FAR = "BEHAVIOR_FOLLOWDIST_STATE_BUTTON_FAR"; const string BEHAVIOR_DEF_MASTER_ON = "BEHAVIOR_DEF_MASTER_STATE_BUTTON_ON"; const string BEHAVIOR_DEF_MASTER_OFF = "BEHAVIOR_DEF_MASTER_STATE_BUTTON_OFF"; const string BEHAVIOR_RETRY_LOCKS_ON = "BEHAVIOR_RETRY_LOCKS_STATE_BUTTON_ON"; const string BEHAVIOR_RETRY_LOCKS_OFF = "BEHAVIOR_RETRY_LOCKS_STATE_BUTTON_OFF"; const string BEHAVIOR_STEALTH_MODE_NONE = "BEHAVIOR_STEALTH_MODE_STATE_BUTTON_NONE"; // 0 const string BEHAVIOR_STEALTH_MODE_PERM = "BEHAVIOR_STEALTH_MODE_STATE_BUTTON_PERM"; // 1 const string BEHAVIOR_STEALTH_MODE_TEMP = "BEHAVIOR_STEALTH_MODE_STATE_BUTTON_TEMP"; // 2 const string BEHAVIOR_DISARM_TRAPS_ON = "BEHAVIOR_DISARM_STATE_BUTTON_ON"; const string BEHAVIOR_DISARM_TRAPS_OFF = "BEHAVIOR_DISARM_STATE_BUTTON_OFF"; const string BEHAVIOR_DISPEL_ON = "BEHAVIOR_DISPEL_STATE_BUTTON_ON"; const string BEHAVIOR_DISPEL_OFF = "BEHAVIOR_DISPEL_STATE_BUTTON_OFF"; //const string BEHAVIOR_CASTING_ON = "BEHAVIOR_CASTING_STATE_BUTTON_ON"; const string BEHAVIOR_CASTING_OFF = "BEHAVIOR_CASTING_STATE_BUTTON_OFF"; const string BEHAVIOR_CASTING_OVERKILL = "BEHAVIOR_CASTING_STATE_BUTTON_OVERKILL"; const string BEHAVIOR_CASTING_POWER = "BEHAVIOR_CASTING_STATE_BUTTON_POWER"; const string BEHAVIOR_CASTING_SCALED = "BEHAVIOR_CASTING_STATE_BUTTON_SCALED"; const string BEHAVIOR_ITEM_USE_ON = "BEHAVIOR_ITEM_USE_STATE_BUTTON_ON"; const string BEHAVIOR_ITEM_USE_OFF = "BEHAVIOR_ITEM_USE_STATE_BUTTON_OFF"; const string BEHAVIOR_FEAT_USE_ON = "BEHAVIOR_FEAT_USE_STATE_BUTTON_ON"; const string BEHAVIOR_FEAT_USE_OFF = "BEHAVIOR_FEAT_USE_STATE_BUTTON_OFF"; const string BEHAVIOR_PUPPET_ON = "BEHAVIOR_PUPPET_STATE_BUTTON_ON"; const string BEHAVIOR_PUPPET_OFF = "BEHAVIOR_PUPPET_STATE_BUTTON_OFF"; const string BEHAVIOR_COMBAT_MODE_USE_ON = "BEHAVIOR_COMBAT_MODE_USE_STATE_BUTTON_ON"; const string BEHAVIOR_COMBAT_MODE_USE_OFF = "BEHAVIOR_COMBAT_MODE_USE_STATE_BUTTON_OFF"; // these str refs double as identifiers for SetBehavior function, so do not set as -1, or make multiple values equal. const int STR_REF_BEHAVIOR_FOLLOWDIST_NEAR = 179925; const int STR_REF_BEHAVIOR_FOLLOWDIST_MED = 179926; const int STR_REF_BEHAVIOR_FOLLOWDIST_FAR = 179927; const int STR_REF_BEHAVIOR_DEF_MASTER_ON = 179928; const int STR_REF_BEHAVIOR_DEF_MASTER_OFF = 179929; const int STR_REF_BEHAVIOR_RETRY_LOCKS_ON = 179930; const int STR_REF_BEHAVIOR_RETRY_LOCKS_OFF = 179931; const int STR_REF_BEHAVIOR_STEALTH_MODE_NONE = 179932; const int STR_REF_BEHAVIOR_STEALTH_MODE_PERM = 179933; const int STR_REF_BEHAVIOR_STEALTH_MODE_TEMP = 179934; const int STR_REF_BEHAVIOR_DISARM_TRAPS_ON = 179936; const int STR_REF_BEHAVIOR_DISARM_TRAPS_OFF = 179937; const int STR_REF_BEHAVIOR_DISPEL_ON = 179938; const int STR_REF_BEHAVIOR_DISPEL_OFF = 179939; //const int STR_REF_BEHAVIOR_CASTING_ON = 179940; const int STR_REF_BEHAVIOR_CASTING_OFF = 179941; const int STR_REF_BEHAVIOR_CASTING_OVERKILL = 182915; const int STR_REF_BEHAVIOR_CASTING_POWER = 182914; const int STR_REF_BEHAVIOR_CASTING_SCALED = 182913; const int STR_REF_BEHAVIOR_ITEM_USE_ON = 183071; const int STR_REF_BEHAVIOR_ITEM_USE_OFF = 183070; const int STR_REF_BEHAVIOR_FEAT_USE_ON = 183216; const int STR_REF_BEHAVIOR_FEAT_USE_OFF = 183215; const int STR_REF_BEHAVIOR_PUPPET_ON = 183222; const int STR_REF_BEHAVIOR_PUPPET_OFF = 183223; const int STR_REF_BEHAVIOR_COMBAT_MODE_USE_ON = 184645; const int STR_REF_BEHAVIOR_COMBAT_MODE_USE_OFF = 184646; //void main(){} //////////////////////////////////// // Prototypes //////////////////////////////////// void SetBehavior(int iStrRef, int iExamined); void SetBehaviorAll(int iStrRef); // doesn't support examined character sheets! void SetBehaviorOnObject(object oSelf, int iStrRef); void GuiBehaviorUpdate (int iExamined); void GuiBehaviorInit(object oPlayerObject, object oTargetObject, string sScreen); //////////////////////////////////// // Functions //////////////////////////////////// // Set Behavior on all companions in the party and on this player's controlled character. void SetBehaviorAll(int iStrRef) { object oPC = OBJECT_SELF; //PrettyMessage("OBJECT_SELF = " + GetName(OBJECT_SELF)); // object oOwnedChar = GetOwnedCharacter(oPC); // OBJECT_SELF is the owned char, and this function will return "" int i = 1; //PrettyMessage("oOwnedChar = " + GetName(oOwnedChar)); object oPartyMember = GetFirstFactionMember(oPC, FALSE); // We stop when there are no more valid PC's in the party. while(GetIsObjectValid(oPartyMember) == TRUE) { //PrettyMessage("SetBehaviorAll: Party char # " + IntToString(i) + " = " + GetName(oPartyMember)); i++; if (GetIsRosterMember(oPartyMember) || (oPartyMember == oPC)) { SetBehaviorOnObject(oPartyMember, iStrRef); } oPartyMember = GetNextFactionMember(oPC, FALSE); } //SetBehavior(iStrRef); object oPlayerObject = GetControlledCharacter(OBJECT_SELF); object oTargetObject = oPlayerObject; string sScreen = SCREEN_CHARACTER; SetGUIObjectText(oPlayerObject, sScreen, BEHAVIORDESC_TEXT, iStrRef, "" ); GuiBehaviorInit(oPlayerObject, oTargetObject, sScreen); } // Set Behavior on currently controlled character void SetBehavior(int iStrRef, int iExamined) { object oPlayerObject = GetControlledCharacter(OBJECT_SELF); object oTargetObject; string sScreen; if (iExamined == 0) // looking at our own character sheet { oTargetObject = oPlayerObject; sScreen = SCREEN_CHARACTER; } else // looking at an examined character sheet { oTargetObject = GetPlayerCreatureExamineTarget(oPlayerObject); sScreen = SCREEN_CREATUREEXAMINE; } SetBehaviorOnObject(oTargetObject, iStrRef); SetGUIObjectText(oPlayerObject, sScreen, BEHAVIORDESC_TEXT, iStrRef, "" ); GuiBehaviorInit(oPlayerObject, oTargetObject, sScreen); } // Set Behavior on object oSelf // oSelf - object to be acted upon // iStrRef - str ref of the description void SetBehaviorOnObject(object oSelf, int iStrRef) { //object oSelf = GetControlledCharacter(OBJECT_SELF); //PrettyMessage("SetBehaviorOnObject: " + GetName(oSelf) + " iStrRef=" + IntToString(iStrRef) ); switch (iStrRef) { case STR_REF_BEHAVIOR_FOLLOWDIST_NEAR: case STR_REF_BEHAVIOR_FOLLOWDIST_MED: case STR_REF_BEHAVIOR_FOLLOWDIST_FAR: SetAssociateState( NW_ASC_DISTANCE_2_METERS, (iStrRef==STR_REF_BEHAVIOR_FOLLOWDIST_NEAR), oSelf ); SetAssociateState( NW_ASC_DISTANCE_4_METERS, (iStrRef==STR_REF_BEHAVIOR_FOLLOWDIST_MED), oSelf ); SetAssociateState( NW_ASC_DISTANCE_6_METERS, (iStrRef==STR_REF_BEHAVIOR_FOLLOWDIST_FAR), oSelf ); break; case STR_REF_BEHAVIOR_DEF_MASTER_ON: SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, TRUE, oSelf); break; case STR_REF_BEHAVIOR_DEF_MASTER_OFF: SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE, oSelf); break; case STR_REF_BEHAVIOR_RETRY_LOCKS_ON: SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, TRUE, oSelf); break; case STR_REF_BEHAVIOR_RETRY_LOCKS_OFF: SetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, FALSE, oSelf); break; case STR_REF_BEHAVIOR_STEALTH_MODE_NONE: //ClearAllActions(); SetLocalInt(oSelf, "X2_HENCH_STEALTH_MODE", 0); SetActionMode(oSelf, ACTION_MODE_STEALTH, FALSE); break; case STR_REF_BEHAVIOR_STEALTH_MODE_PERM: ClearAllActions(); SetLocalInt(oSelf, "X2_HENCH_STEALTH_MODE", 1); DelayCommand(1.0, SetActionMode(oSelf, ACTION_MODE_STEALTH, TRUE)); break; case STR_REF_BEHAVIOR_STEALTH_MODE_TEMP: ClearAllActions(); SetLocalInt(oSelf, "X2_HENCH_STEALTH_MODE", 2); DelayCommand(1.0, SetActionMode(oSelf, ACTION_MODE_STEALTH, TRUE)); break; case STR_REF_BEHAVIOR_DISARM_TRAPS_ON: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_DISARM_TRAPS_ON"); SetAssociateState(NW_ASC_DISARM_TRAPS, TRUE, oSelf); break; case STR_REF_BEHAVIOR_DISARM_TRAPS_OFF: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_DISARM_TRAPS_OFF"); SetAssociateState(NW_ASC_DISARM_TRAPS, FALSE, oSelf); break; case STR_REF_BEHAVIOR_DISPEL_ON: SetLocalInt(oSelf, "X2_HENCH_DO_NOT_DISPEL", FALSE); break; case STR_REF_BEHAVIOR_DISPEL_OFF: SetLocalInt(oSelf, "X2_HENCH_DO_NOT_DISPEL", TRUE); break; case STR_REF_BEHAVIOR_CASTING_OFF: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_CASTING_OFF"); SetLocalInt(oSelf, "X2_L_STOPCASTING", 10); // casting off is 10 for this break; case STR_REF_BEHAVIOR_CASTING_OVERKILL: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_CASTING_OVERKILL"); SetLocalInt(oSelf, "X2_L_STOPCASTING", 0); SetAssociateState(NW_ASC_OVERKIll_CASTING, TRUE, oSelf); SetAssociateState(NW_ASC_POWER_CASTING, FALSE, oSelf); SetAssociateState(NW_ASC_SCALED_CASTING, FALSE, oSelf); break; case STR_REF_BEHAVIOR_CASTING_POWER: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_CASTING_POWER"); SetLocalInt(oSelf, "X2_L_STOPCASTING", 0); // casting on is 0 for this SetAssociateState(NW_ASC_OVERKIll_CASTING, FALSE, oSelf); SetAssociateState(NW_ASC_POWER_CASTING, TRUE, oSelf); SetAssociateState(NW_ASC_SCALED_CASTING, FALSE, oSelf); break; case STR_REF_BEHAVIOR_CASTING_SCALED: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_CASTING_SCALED"); SetLocalInt(oSelf, "X2_L_STOPCASTING", 0); SetAssociateState(NW_ASC_OVERKIll_CASTING, FALSE, oSelf); SetAssociateState(NW_ASC_POWER_CASTING, FALSE, oSelf); SetAssociateState(NW_ASC_SCALED_CASTING, TRUE, oSelf); break; // to use items we set item exclusion to false case STR_REF_BEHAVIOR_ITEM_USE_ON: SetLocalIntState(oSelf, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ITEM, FALSE); break; // to not use items we set item exclusion to true case STR_REF_BEHAVIOR_ITEM_USE_OFF: SetLocalIntState(oSelf, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ITEM, TRUE); break; // to use abilities (feats, skills, and special abilities) we set ability exclusion to false case STR_REF_BEHAVIOR_FEAT_USE_ON: SetLocalIntState(oSelf, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ABILITY, FALSE); break; // to not use abilities we set ability exclusion to true case STR_REF_BEHAVIOR_FEAT_USE_OFF: SetLocalIntState(oSelf, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ABILITY, TRUE); break; case STR_REF_BEHAVIOR_PUPPET_ON: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_PUPPET_ON"); SetAssociateState(NW_ASC_MODE_PUPPET, TRUE, oSelf); break; case STR_REF_BEHAVIOR_PUPPET_OFF: //PrettyMessage("SetBehavior: STR_REF_BEHAVIOR_PUPPET_OFF"); SetAssociateState(NW_ASC_MODE_PUPPET, FALSE, oSelf); break; case STR_REF_BEHAVIOR_COMBAT_MODE_USE_ON: SetLocalInt(oSelf, N2_COMBAT_MODE_USE_DISABLED, FALSE); break; case STR_REF_BEHAVIOR_COMBAT_MODE_USE_OFF: SetLocalInt(oSelf, N2_COMBAT_MODE_USE_DISABLED, TRUE); break; default: PrettyError( "gui_bhvr_inc: Behavior " + IntToString( iStrRef ) + " definition does not exist." ); break; } } // this func called by gui_bhvr_update void GuiBehaviorUpdate (int iExamined) { //object oSelf; string sScreen; object oPlayerObject = GetControlledCharacter(OBJECT_SELF); object oTargetObject; if (iExamined == 0) // looking at our own character sheet { oTargetObject = oPlayerObject; sScreen = SCREEN_CHARACTER; } else // looking at an examined character sheet { oTargetObject = GetPlayerCreatureExamineTarget(oPlayerObject); sScreen = SCREEN_CREATUREEXAMINE; } GuiBehaviorInit(oPlayerObject, oTargetObject, sScreen); } // set up the GUI with all the info for the selectable states // oPlayerObject - the player object who's looking at the GUI // oTargetObject - the object who's information is being displayed in the GUI // sScreen - The GUI screen being looked at. void GuiBehaviorInit(object oPlayerObject, object oTargetObject, string sScreen) { int iState; //object oSelf = GetControlledCharacter(OBJECT_SELF); //PrettyMessage("gui_bhvr_update: oSelf=" + GetName(oTargetObject) + " sScreen=" + sScreen); // *** Follow Distance if ( GetAssociateState( NW_ASC_DISTANCE_2_METERS, oTargetObject ) ) { SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_NEAR, TRUE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_MED, FALSE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_FAR, FALSE ); } else if ( GetAssociateState( NW_ASC_DISTANCE_4_METERS, oTargetObject ) ) { SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_NEAR, FALSE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_MED, TRUE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_FAR, FALSE ); } else if ( GetAssociateState( NW_ASC_DISTANCE_6_METERS, oTargetObject ) ) { SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_NEAR, FALSE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_MED, FALSE ); SetGUIObjectDisabled( oPlayerObject, sScreen, BEHAVIOR_FOLLOWDIST_FAR, TRUE ); } //iState = //SetGUIObjectDisabled( oSelf, sScreen, BEHAVIOR_FOLLOWDIST_STATE_BUTTON_NEAR, (iState==NW_ASC_DISTANCE_2_METERS) ); //SetGUIObjectDisabled( oSelf, sScreen, BEHAVIOR_FOLLOWDIST_STATE_BUTTON_MED, (iState==NW_ASC_DISTANCE_4_METERS) ); //SetGUIObjectDisabled( oSelf, sScreen, BEHAVIOR_FOLLOWDIST_STATE_BUTTON_FAR, (iState==NW_ASC_DISTANCE_6_METERS) ); // defend master mode iState = GetAssociateState(NW_ASC_MODE_DEFEND_MASTER, oTargetObject); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DEF_MASTER_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DEF_MASTER_OFF, (!iState)); // retry open locks mode iState = GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oTargetObject); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_RETRY_LOCKS_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_RETRY_LOCKS_OFF, (!iState)); // stealthy mode iState = GetLocalInt(oTargetObject, "X2_HENCH_STEALTH_MODE"); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_STEALTH_MODE_NONE, (iState==0) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_STEALTH_MODE_PERM, (iState==1)); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_STEALTH_MODE_TEMP, (iState==2)); // Disarm traps iState = GetAssociateState(NW_ASC_DISARM_TRAPS, oTargetObject); //PrettyMessage("GuiBehaviorInit(): iState =" + IntToString(iState)); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DISARM_TRAPS_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DISARM_TRAPS_OFF, (!iState)); // Displel mode iState = (GetLocalInt(oTargetObject, "X2_HENCH_DO_NOT_DISPEL") == FALSE); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DISPEL_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_DISPEL_OFF, (!iState)); // Casting mode iState = (GetLocalInt(oTargetObject, "X2_L_STOPCASTING") == 0); //SetGUIObjectDisabled(oSelf, sScreen, BEHAVIOR_CASTING_ON, (iState) ); //SetGUIObjectDisabled(oSelf, sScreen, BEHAVIOR_CASTING_OFF, (!iState)); //PrettyMessage("GuiBehaviorInit(): iState =" + IntToString(iState)); if (iState == FALSE) { SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_OVERKILL, FALSE ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_POWER, FALSE ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_SCALED, FALSE ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_OFF, TRUE); } else { SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_OVERKILL, GetAssociateState( NW_ASC_OVERKIll_CASTING, oTargetObject ) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_POWER, GetAssociateState( NW_ASC_POWER_CASTING, oTargetObject ) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_SCALED, GetAssociateState( NW_ASC_SCALED_CASTING, oTargetObject ) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_CASTING_OFF, FALSE); } // Use Items //iState = (GetLocalInt(oSelf, N2_TALENT_EXCLUDE) == 0); // 1st bit is item usage iState = (GetLocalIntState(oTargetObject, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ITEM) == FALSE); //PrettyMessage("GuiBehaviorInit(): iState =" + IntToString(iState)); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_ITEM_USE_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_ITEM_USE_OFF, (!iState)); // Use Items iState = (GetLocalIntState(oTargetObject, N2_TALENT_EXCLUDE, TALENT_EXCLUDE_ABILITY) == FALSE); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_FEAT_USE_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_FEAT_USE_OFF, (!iState)); // Puppet Mode iState = GetAssociateState(NW_ASC_MODE_PUPPET, oTargetObject); //PrettyMessage("GuiBehaviorInit(): iState for " + GetName(oSelf) + " (Puppet Mode)=" + IntToString(iState)); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_PUPPET_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_PUPPET_OFF, (!iState)); // Use Combat Mode iState = (GetLocalInt(oTargetObject, N2_COMBAT_MODE_USE_DISABLED) == FALSE); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_COMBAT_MODE_USE_ON, (iState) ); SetGUIObjectDisabled(oPlayerObject, sScreen, BEHAVIOR_COMBAT_MODE_USE_OFF, (!iState)); } // gui_bhvr_item_use_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/7/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_ITEM_USE_OFF, iExamined); } // gui_bhvr_item_use_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/7/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_ITEM_USE_ON, iExamined); } // gui_bhvr_puppet_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/9/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_PUPPET_OFF, iExamined); } // gui_bhvr_puppet_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 8/9/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_PUPPET_ON, iExamined); } // gui_bhvr_retry_locks_off /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_RETRY_LOCKS_OFF, iExamined); } // gui_bhvr_retry_locks_on /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_RETRY_LOCKS_ON, iExamined); } // gui_bhvr_stealth_none /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_STEALTH_MODE_NONE, iExamined); } // gui_bhvr_stealth_perm /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_STEALTH_MODE_PERM, iExamined); } // gui_bhvr_stealth_temp /* Behavior script for the character sheet behavior sub-panel */ // ChazM 4/26/06 // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { SetBehavior(STR_REF_BEHAVIOR_STEALTH_MODE_TEMP, iExamined); } //:://///////////////////////////////////////////// //:: Behavior Screen - Update //:: gui_bhvr_update.nss //:: Created By: Brock Heinz - OEI //:: Created On: 03/29/06 //::////////////////////////////////////////////// // ChazM 4/26/06 - changed to use inc file // ChazM 11/9/06 - Examined Creature update #include "gui_bhvr_inc" void main(int iExamined) { GuiBehaviorUpdate(iExamined); } // gui_death_exitgame.nss /* Death GUI 'Exit Game' callback */ // BMA-OEI 6/29/06 #include "ginc_debug" void main() { string sFile = "gui_death_exitgame"; PrettyDebug( sFile + ": EndGame() - TODO: confirmation dialog" ); EndGame( "" ); } // gui_death_hidden_click.nss /* Hidden Death GUI 'Click' callback */ // BMA-OEI 6/29/06 #include "ginc_death" void main() { object oPC = OBJECT_SELF; RemoveDeathScreens( oPC ); // Check if there are any members left for PC to possess if ( GetIsDead(oPC) == TRUE ) { if ( GetIsPartyPossessible(oPC) == FALSE ) { ShowProperDeathScreen( oPC ); } } } // gui_death_loadgame.nss /* Death GUI 'Load Game' callback */ // BMA-OEI 6/29/06 // BMA-OEI 9/01/06: Override "Save First?" dialog in UIScene_OnAdd_CreateLoadGameList() #include "ginc_death" #include "ginc_gui" void main() { // BMA-OEI 9/01/06: Override "Save First?" dialog in UIScene_OnAdd_CreateLoadGameList() SetLocalGUIVariable( OBJECT_SELF, GUI_LOAD_GAME, 3, "1" ); HideDeathScreen( OBJECT_SELF ); ShowHiddenDeathScreen( OBJECT_SELF ); ShowLoadGame( OBJECT_SELF ); } // gui_death_respawn.nss /* Death GUI 'Respawn' callback: wake up groggy */ // BMA-OEI 6/29/06 #include "ginc_death" void main() { // Resurrect PC object oPC = OBJECT_SELF; WakeUpCreature( oPC ); RemoveDeathScreens( oPC ); // Apply Groggy penalty effect eGroggy = EffectDazed(); //eGroggy = EffectLinkEffects( EffectSlow(), eGroggy ); ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eGroggy, oPC, RoundsToSeconds( 2 ) ); } // gui_death_respawn_self.nss /* NWN2 Default Death Screen 'Respawn' callback */ // BMA-OEI 7/20/06 // BMA-OEI 11/08/06 -- Close SCREEN_DEATH_DEFAULT #include "ginc_death" void main() { ResurrectCreature( OBJECT_SELF ); CloseGUIScreen( OBJECT_SELF, "SCREEN_DEATH_DEFAULT" ); } // gui_death_waitforhelp.nss /* Death GUI 'Wait For Help' callback: displays full-screen hidden death button */ // BMA-OEI 08/06/06 #include "ginc_death" void main() { object oPC = OBJECT_SELF; ShowHiddenDeathScreen( oPC ); HideDeathScreen( oPC ); } // gui_force_comp // // A companion is forced into the party, and the party gui is brought up. // This is a callback script called from ka_hotspot_click_force. The function DisplayForceCompanionMessage() defines // the companion who gets forced into the party, setting it as a global variable. // EPF 1/10/06 // BMA-OEI 8/31/06: Delay to DisplayGuiScreen, Use OBJECT_SELF as PC // BMA-OEI 9/17/06: If there's room, force companion into party // BMA-OEI 9/17/06: No longer displays Party Select ( Trigger already prompts Party Select ) // BMA-OEI 10/20/06: " " Unless opened in area other than Crossroad Keep #include "ginc_companion" #include "ginc_gui" void main() { object oPC = OBJECT_SELF; if ( GetIsPC(oPC) == FALSE ) return; object oFM; string sCompanion = GetGlobalString("00_sLastForcedCompanion"); // BMA-OEI 9/17/06: If there's room, force companion into party int nPartyLimit = GetRosterNPCPartyLimit(); int nNPCsInParty = GetNumRosterMembersInParty( oPC ); // Party Limit hit, remove selectable companions if ( nNPCsInParty >= nPartyLimit ) { RemoveRosterMembersFromParty( oPC, TRUE, FALSE ); nNPCsInParty = GetNumRosterMembersInParty( oPC ); } // Free slots available, add required companion if ( nNPCsInParty < nPartyLimit ) { AddRosterMemberToParty( sCompanion, oPC ); SetIsRosterMemberSelectable( sCompanion, FALSE ); } /* AddRosterMemberToParty(sCompanion,oPC); SetIsRosterMemberSelectable(sCompanion,FALSE); oFM = GetFirstFactionMember(oPC,FALSE); while(GetIsObjectValid(oFM)) { if(GetIsRosterMember(oFM) && GetIsRosterMemberSelectable(GetRosterNameFromObject(oFM))) { RemoveRosterMemberFromParty(GetRosterNameFromObject(oFM),oPC); } oFM = GetNextFactionMember(oFM,FALSE); } */ // BMA-OEI 10/20/06: Unless opened in area other than Crossroad Keep // BMA-OEI 9/17/06: No longer displays Party Select ( Trigger already prompts screen ) // BMA-OEI 8/31/06: Delay for GUI to update w/ spawned companion if ( GetTag( GetArea( oPC ) ) != "3070_sh_farm" ) { DelayCommand( 0.5f, ShowPartySelect( oPC, TRUE, "", FALSE ) ); } } // gui_input_ok void main( string sInput ) { ActionSpeakString( sInput ); } // gui_map_transition /* Transitions party to a waypoint set in a global variable. */ // EPF 8/18/06 // ChazM 8/22/06 - removed "kinc_worldmap" dependency. //#include "kinc_worldmap" #include "ginc_companion" #include "ginc_transition" // const string LAST_DESTINATION = "00_sLastDestination"; const string LAST_MODULE = "00_sLastModule"; const string PC_CLICKER = "oLastWorldMapClicker"; //this is stored on the module not void main() { string sDestination = GetGlobalString(LAST_DESTINATION); string sModule = GetGlobalString(LAST_MODULE); object oPC = GetLocalObject(GetModule(), PC_CLICKER); object oDestination = GetObjectByTag(sDestination); SetCommandable(TRUE,oPC); ForceRestParty(oPC); if(GetIsObjectValid(oDestination)) { SinglePartyTransition( oPC, oDestination ); } else { SaveRosterLoadModule(sModule, sDestination); } } // gui_name_enchanted_item /* rename weapon user has just enchanted w/ the input string. */ // ChazM 5/24/06 // ChazM 5/31/06 Update to reflect where Item object is now stored // ChazM 9/29/06 Just comments #include "ginc_crafting" void main( string sName ) { //PrettyDebug("gui_name_enchanted_item called!"); // Item object is stored on the character which opened the GUI panel. object oObj = OBJECT_SELF; //GetOwnedCharacter(OBJECT_SELF); object oItem = GetLocalObject(oObj, VAR_ENCHANTED_ITEM_OBJECT); //PrettyDebug("gui_name_enchanted_item: oObj=" + GetName(oObj) + "| oItem=" + GetName(oItem)+ "| sName=" + sName); if ((sName != "") && (GetIsObjectValid(oItem))) { //PrettyDebug("setting new name!"); SetFirstName(oItem, sName); } // else {PrettyDebug("NOT setting new name - either name is empty string or item object is invalid."); } DeleteLocalObject(oObj, VAR_ENCHANTED_ITEM_OBJECT); } Apendix ga_alignment ga_attack ga_attack_target ga_blackout ga_camera_facing_point_party ga_clear_comp ga_commandable ga_compshift ga_conversation_self ga_create_obj ga_cutscene_move ga_date_advance ga_date_set ga_death ga_destroy ga_destroy_item ga_destroy_party_henchmen ga_disable_scripts ga_donothing ga_door_close ga_door_open ga_effect ga_enable_scripts ga_end_game ga_face_target ga_faction_join ga_faction_rep ga_fade_from_black ga_fade_to_black ga_floating_str_ref ga_floating_text ga_force_exit ga_gint_max ga_gint_min ga_give_feat ga_give_gold ga_give_inventory ga_give_item ga_give_item_global_int ga_give_partial_quest_xp ga_give_quest_xp ga_give_xp ga_global_float ga_global_int ga_global_string ga_heal_pc ga_henchman_add ga_henchman_remove ga_henchman_replace ga_henchman_setmax ga_journal ga_jump ga_jump_faction ga_jump_party_in_formation ga_jump_players ga_load_mod ga_local_float ga_local_int ga_local_string ga_lock ga_mapnote ga_move ga_move_exit ga_music_battle_play ga_music_battle_restore ga_music_battle_save ga_music_battle_set ga_music_battle_stop ga_music_play ga_music_restore ga_music_save ga_music_set ga_music_stop ga_object_events_clear ga_object_events_restore ga_open_store ga_party_add ga_party_face_target ga_party_freeze ga_party_limit ga_party_unfreeze ga_play_animation ga_play_custom_animation ga_play_sound ga_play_voice_chat ga_reequip_all_items 1234PQRSdefֵyjyYjNj:&h_5;OJQJ\^JmHnHuh8mHnHu j}h_UmHnHujh_UmHnHuh_mHnHu2jh%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu$jh%Ch_0JUmHnHuhgh_5>*CJaJ#jhgh_5>*CJUaJ#h}h_5CJOJQJ^JaJ h_>*9 < : 6    ! # D ~&&2&2&2&2&2&2&2&v:&&v:&v:gd}gd_gd_S[n[   1 2 3 λ񰡰qW񰡰F jqh_UmHnHu2jh%Ch_>*B*UmHnHphu&h_5;OJQJ\^JmHnHuh8mHnHu jwh_UmHnHujh_UmHnHuh_mHnHu$jh%Ch_0JUmHnHu2jh%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu3 6 7 8 9 : ; W X Y Z q r s ӿӱӱrӿӱXӱ2jh%Ch_>*B*UmHnHphu jkh_UmHnHuh_mHnHu2jh%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu&h_5;OJQJ\^JmHnHu$jh%Ch_0JUmHnHujh_UmHnHuh8mHnHu    4 5 6 9 : ; < = > Z [ \ ® } rra® G2jh%Ch_>*B*UmHnHphu j_h_UmHnHuh_mHnHu2jh%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu&h_5;OJQJ\^JmHnHu$jh%Ch_0JUmHnHuh8mHnHujh_UmHnHu jeh_UmHnHu\ ] r s t   Դũߌraũߌ jSh_UmHnHu2jh%Ch_>*B*UmHnHphuh_mHnHu&h_5;OJQJ\^JmHnHuh8mHnHu jYh_UmHnHujh_UmHnHuh_mHnHuh%Ch_0JmHnHu$jh%Ch_0JUmHnHu      2 3 4 7 8 9 : ; < X Y Z [ l m n ź{rXźG jG h_UmHnHu2jh%Ch_>*B*UmHnHphuh_mHnHu&h_5;OJQJ\^JmHnHuh8mHnHu jMh_UmHnHujh_UmHnHuh_mHnHuh%Ch_0JmHnHu$jh%Ch_0JUmHnHu2jh%Ch_>*B*UmHnHphu        . ˨˝}rX˝2j h%Ch_>*B*UmHnHphuh8mHnHu jA h_UmHnHujh_UmHnHuh_mHnHu2j h%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu$jh%Ch_0JUmHnHu&h_5;OJQJ\^JmHnHu. / 0 3 4 5 6 7 8 T U V W n o p ® } rra® G2j h%Ch_>*B*UmHnHphu j5 h_UmHnHuh_mHnHu2j h%Ch_>*B*UmHnHphuh_mHnHuh%Ch_0JmHnHu&h_5;OJQJ\^JmHnHu$jh%Ch_0JUmHnHuh8mHnHujh_UmHnHu j; h_UmHnHu   # $ % D E Ҳç퓁zk\k\Mk?jhL6CJUaJh,^6CJ4OJQJ^JaJ4hr6CJ4OJQJ^JaJ4h}6CJ4OJQJ^JaJ4 h_5>*#jhgh_5>*CJUaJ&h_5;OJQJ\^JmHnHuh8mHnHu j/ h_UmHnHujh_UmHnHuh_mHnHuh%Ch_0J6mHnHu$jh%Ch_0JUmHnHuE X k m n o }~ŷ稟{l{l{l{l{lcZSL hfhf hFq5>*hg>*CJ aJ hc>*CJ aJ h}5CJOJQJ^JaJ#h}h}5CJOJQJ^JaJh}>*CJ aJ h,^>*CJ aJ hr>*CJ aJ h}6CJ4OJQJ^JaJ4h!|1hL0J6CJaJjhL6CJUaJ&j h!|1hL6CJUaJhL6CJOJQJ^JaJhL6CJaJ~qH1l$^ |~&v:&v:&v:&v:&&&&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfgdfgd}gd}|5""###$$$%%&''''''r(s(t(++r+,,,T-k.l.m.../|0}0111Y2Z2[2333$45555>6@6R6T6t6=7>7?7:::<<<=>>>???hfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphO~&Gk"Eh~579w{&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf%BSo5Fd'Hdu&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfuy|/2468vz;Ll&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf1B^y ?[lps  # % ' ) U X &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfX !p!!!!!"o""""""""""""P#R#b###&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf#####$$.$1$m$$$$$$%%j%l%|%%%%&&&.&G&I&v&&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfv&y&&&''''&'+''''''''''J(L(n(q(r(s(((()=)&1&1&1&10%a0%10%10%10%10%10%10%10%10%10%10%10%10%1 &a &1 &1 &1 &1gdf=)@))))*Q*y*|** + ++!+r+t++++++-,0,,,,,,,, &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf,T-x-------..c.g.j.k.l......,/q///////B0 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfB0D0x0{0|0}0000011115171d1g11111O2R2U2X2Y2Z2l2p2 &1 &1a1111111111111111111$a$1gdfp2223^33333344 4(4k4m4444444 5G5o555555$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdf5555556<6@6R6T6t6w6666697<7=7>77777 8U8888 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1gdf8909p99 :Q:::::::;(;*;;;;<A<C<<<<<<<$=^= &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1`"a`"1`"1`"1gdf^========>>1>5><>@>c>g>j>>>>>>??'?*?P?x???`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1a1111111gdf????? @:@a@c@|@@@@@@@@@@@"A[AAAAAAAAB111111111111 a 1 1 1 1 1 1 1 1 1 1 1 1 1gdf?g@|@@@@AAAAABBBCCDIISKKKKKONQNNN0OOOP Q+R?RlRRS-S{SSSSBTpTTTTUUUW3WXXXYY ZZZ\\\]]s]]#dddddd eeee ffhfB* CJ^JaJphhfB*^Jph!h= hfB* CJ^JaJphhfB*CJ^JaJphOBBBB+B/BZBB CCCCCCCCNDDDDDEEiEEEEEEFAF%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdfAFCFFFFG?GGGGGGGHHJHoHHHH7I>IAICIpIsIIIII%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdfIJJ0J7JzJ|JJJKFKMKOKKKKKKKKK2LLLMlMM NKNMN%1%1%1%1%1%1%1%1%1%1%1%1%1%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfMNQN`NNNNN0OxO{OOOO P P6PAPoPPPPPP QUQ\Q_QaQcQeQ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfeQQQQQ?RAR]RdRRRSS-SsSSSS5TTpTTTTTTTTT &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &agdfTTT(UUUUUUUUU;V>VSVVVVVVW3WRWiWtWWWWWW &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfWWWWWXhXXXXXY YDYzYYYYYYY ZZCZZZZZ[Z[ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfZ[i[{[[[[[[\%\,\g\v\\\\\\\\\]]&]C]s]u]]]] &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf]]]]^^B^F^N^^^^^^_#_&_(_?_}____`4`Q`T`V``` &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf`````3aaadaaaaab7bbbbbb$c'cbcccccdd!d%d &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf%d2d5ddddddddddde e(eHeKegejeeeeeeeeee f &1 &1 &1 &1 &1a11111111111111%a%1%1gdf ff"fLfPfgfjffffgggg(g,gDgtgggggggg%h'hthhh%1%1%1%1%1%1%1%1%1%1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1gdffLfgggggghhh i iiiiioopRvsvz{{|,}-}.}n}p}}^~_~`~~~~~Z\݀efgVWX#%8HKՏKM“ACU ShfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphOhhhhhhhi iii4i7i9ieigiiiiiiiii6jcjj k=kk#a#1#1#1#1#1#1#1#1#1#1#1#1#1#1(a(1(1(1(1(1(1(1gdfkll=llllim~mmmmJn`nnnno)o.o;ooooooMpppp(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdfpqqq~qqqqqrUrXrZr\rrrs"sRs~ssssssss"t{tt(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdfttt+uTu_u}uuuuuPvsvvvvvvvwKwewnwwwwwwx.x(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdf.x7xTxsxxxxxy+y4yoyyyyy zzzMzXz\z_zyz~zzzz{A{(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdfA{F{{{{{|4|<|@|G||(}+},}-}D}H}l}p}}}}}}}}~0~U~(1(1(1(1(1(1(1(1(1(1(1(10a01010101010101010101010101gdfU~Z~]~^~_~~~~~~~~~CFVX\p݀߀WZ01a1111%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdfZ݁߁4_adef{^468knʄ̈́%1%1%1%1%1%1%1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1gdf̈́W]fԅORUVWkoc!%8:Wqsu@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdfu+2Vahj ZH3e'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdfe .2Տ׏ _a'1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1&agdf^KM AEa“ēޓ-0&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf?CUWnpڕ SĖ֖ؖ 0%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%a0%10%10%10%10%10%10%10%10%1gdf–Ė֖]ȗɗʗFٝݝ1͟26РѠҠ£ԣ-/}rt *cde}ɴ߶ACSV|ϸиhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphhfB* CJ^JaJphO \ėǗȗɗܗHRԘ٘OFH^a0%10%10%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf8=Mʛ.KhĜ?qם۝ݝ&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf VY[؞ܞ1E\p͟ҟڟ2̠&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf̠ϠРѠ!1gʡ/Li#Uw£ԣ֣&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf֣:=?j٤ޤ)@Ttԥڥܥ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfƦʦH+/>}ި=?UYp&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf$GSX\dhŪɪ*pt&1&1&1&1&1&1&1&1&1&1&1&1&10%a0%10%10%10%10%10%10%10%10%10%10%10%1gdf7AHnϬ #'twǭ @*0%10%10%10%10%10%10%10%10%10%10%10%1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gdf*,.DadޯCxzΰٰ #P[_bcd&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1gdf±űӱ6{L³ijZ]´ƴȴ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf-1gkrv psv϶׶۶޶߶&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&agdfV?CSV|ϸAb{Թ1Z]wǺغ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfиԹչ1^wǺμ ^aqHIJVXeL\ C:M  P]_l >BhfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphOغۺݺ/2;>UYƻ˻ӻ.48;=x{ʼͼ 7:Vh&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfhlƽ\~l̿/^aqt&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf DGHI_cjTXe &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &10%a0%10%10%10%10%10%1gdfeg#Iq|49I0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1&a&1&1&1&1&1&1&1&1&1gdf:ZzFJ\CozM&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfM\ix/:r} Xgy)8C&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfCJT[  V[k4Li&1&1&1&1&1&1&1&1&1&1%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdf ?BDoPR{~[_ln%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%a%1%1%1%1%1%1%1gdfn>$479Yl%1%1%1%1%1%1%1%1%1%1%1%1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gdf=DvFbik =-bm&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfmtvyz{:@YF')F`bdf&1&1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdfz{'#qS5M$<4W3pYz-I_a{ 7 + hfB* CJ^JaJph!h= hfB* CJ^JaJphhfB*^JphhfB*CJ^JaJphO-4Sqs"grvx )/(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1 &a &1 &1 &1 &1 &1 &1gdf#)z#Y\vy'+.MP &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfflNlCSUr &1 &1 &1 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf!#Mho<W^xWp&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfFQUXzJPio2Wx4V&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfV\-IKMOjm`d<)&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1gdfWZUY%]apAD &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfDuhl$R7: &1 &1 &1 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf:zZ~  QUH]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf]s.2 ${2MPm &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfm7;=@X\g kv1<H &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfHLZ^`  ] &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1&1&1&1&1gdf 5   5 7 S   + x {       > B D F u |   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf   6 = ? v x z     ' , i p s u   9;&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf 3eilmn?B25Evx@&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&agdf 35emno?B25v24R|>@ !""&"'"("##$Z%[% ''''''(0)1)2)** +---W.Y..%/Q///01019999:hfB* CJ^JaJphhfB*^Jph!h= hfB* CJ^JaJphhfB*CJ^JaJphO@D{0Kf04Aj24p&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfKpw'epQ`r(7BIy&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf7B|#2DS %,W^&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1$agdf^b+Haz<@Mv  # < > { ~   $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdf !!!R!!!!!""%"&"'"m"r"""""4######$$4$6$r$u$$1$1$1$1$1$1$1$1%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdfu$$$&%V%Y%Z%[%%%%%&(&.&&&&&& ' '*','S'V'|'~'''%1%1%1%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf'''''''(d((((((((,)/)0)1)>)B)i)))W*****0%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%1&a&1&1&1&1&1&1&1&1&1gdf* +$+A+C+y+|+~++++ ,+,/,u,,,,,,, - ----$-(-u--&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&10%a0%10%10%1gdf--.U.Y.f..... / /!/$/Q/}///////001080<0_0c0f00%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdff0y0|0~0000 131l1111112(2Y2d22223&3H3V3a33330%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdf33,4d444444 5M5556I6|666 7797]7h7778!8-8880%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdf888(9x999999999::::#:&:E:H:e:i::::::::0%10%10%10%10%10%10%1pap1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1gdf::::::4;6;F;<<<<<<`=a=b=]G_GoG1H2H3HxHzHH9I:I;I}IIIBJCJDJJJJiKjKkKKKKLLLUWWWgWDYEYFYYYYMZNZOZZZ[[[[b\d\v\@]A]B]b^d^^^___C`hfB* CJ^JaJphhfB*^Jph!h= hfB* CJ^JaJphhfB*CJ^JaJphO::::2;6;F;H;_;a;n;q;;;;;;;;;<<<<1<5<<<<<@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1"a"1"1"1"1"1gdf<<<<<<<<===:===\=_=`=a=z=~===>>+>0>D>R>d>x>>"1"1"1"1"1"1"1"1"1"1"1"1"1#a#1#1#1#1#1#1#1#1#1#1#1#1gdf>>>>>>??!?1?H?_?q???????? @@-@;@O@d@w@@@@#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdf@@@A.AGA`AAAAAAAB/BKBcByBBBBBBCCC1CKCaCtC#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdftCCCCCCCCD0DDDWDoDDDDDDDDEE(E6EQEjEEEEE#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdfEEEF/FKF_FFFFFFGG-GHGMGVG[G_GoGqGGGGGGGGG#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdfGH H-H0H1H2HLHPHvHzHHHHHHHHHHHII5I8I9I:IMIQI{I#1#1#1pap1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1a11gdf{IIIIIIIIIIIIJ J>JAJBJCJYJ]JJJJJJJJJJJ11111111111111@a@1@1@1@1@1@1@1@1@1@1@1gdfJK K"K&KFKIKeKhKiKjK}KKKKKKKKL L)L,LILMLcLgLLLL@1@1@1@1@1@1@1"a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gdfLLLLLLLL&M+M[MMMMMNN$N)N=NKN]NqNNNNNNNN#a#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdfN OO*OAOXOjO~OOOOOOOPP&P4PHP\PoPPPPPPQ&Q?QXQ#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdfXQ{QQQQQQ R'RCR[RqRRRRRRR SS)SCSYSlSSSSSSS#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdfSS T(T &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf>dׅۅ!4s82|׈݈i &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf݉04;?*,GJp &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1a11111111111gdfjn׌ڌHJnqrsύэ&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&10%a0%10%1gdfэ6}Ў$ACdg!CGtx0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1&agdftÐfghdfw՗ "D\Ęܘ b*YRcƛ&tМ0Aҝ؝>}RsĢIg ehfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphO֐ڐb ;>Ndhϒђ.Q]bfn&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfnrLP`qĔߔeg5bef&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdffgz~bfwy DĘ \^əЙ $&Yq &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfqxƚښ&:cƛ&H\Afzҝԝ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfԝWYIyڟ8:}/:sˡ\u &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfĢ2g֣ Ibz +24_=~ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1gdf~*eg~ŧȧ*.z~ب>Bͩ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&10%a0%10%10%1gdfͩϩݩ(%UY79R0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1(a(1(1(1(1(1(1(1gdf79BDT2MȲ͸3,0Ӽռؽٽ,23 +-?79MPRe  hfB* CJ^JaJph!h= hfB* CJ^JaJphhfB*^JphhfB*CJ^JaJphOR7jʭBDTVXZ\y̮ήЮҮ #Jlw{ԯ(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdf&Xڰ 6;Zű+.MIJ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdfU׳f>{'aضNȷ E}3V|(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdf,~0 kn|Ѽռ(1(1(1(1(1(1(1(1(1(1(1(1(1(1&a&1&1&1&1&1&1&1&1&1&1&1gdf!>AwzԽ׽ؽٽ*0HNܾCIԿۿ,.&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf.EGx{9=DH"l*P&1&1&1&1&1&1&1&1&1&1&1&1&1"a"1"1"1"1"1"1"1"1"1"1"1"1"1gdf*-123KOc"`zIL"1"1"1"1"a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gdfF_ CF&s0%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1@$a@$1@$1@$1@$1@$1@$1@$1gdf)-?A^a59MOjl@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1`"a`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1%a%1gdfNRehux   #'X[o;[&%1%1%1%1%1%1%1%1%1%1%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf&AF=14c &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 a 1 1 1 1 1 1 1 1 1 1 1 1 1 1gdfcf#[^l-/dg 1 1 1 10%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdf qw0KQ2{ &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1P#aP#1P#1P#1P#1P#1gdf EGY%FG$%&yz{@BLPefgij#$4;vwhfB* CJ^JaJph!h= hfB* CJ^JaJphhfB*^JphhfB*CJ^JaJphO{U*o@CGY\P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1gdfQ(e%'DG?BEF@$1@$1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1gdfFGcg VYi$5KMim #$0%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdf$%:>w|AE03g# &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1%agdf#')j\4wDY%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdf'*Quxyz<>BLNPTkmy%1%1%1%1%1%1%1%1%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf Op$\&(9')c3np &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf&_ "\  25adefx| &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &10%a0%10%10%10%1gdf"?dhij'QVY0%10%10%10%10%10%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdf#(Ls 49n 7 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &agdf7;uS;=Qnpv&)+`c &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfGf 14Y\]^xax1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1#a#1#1#1#1gdf]^_EG[   r t `d}4g$$%&&''c,,,<-p----..A.v.... //R/a/////0%0Z0g000001-1b1n11111+2hfB* CJ^JaJphhfB*^Jph!h= hfB* CJ^JaJphhfB*CJ^JaJphOCG[]z $;@V[ch#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1gdf48ehv/1[^   "a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gdf " $ H L S W         H J _     p t     P  "1"1"1"1"1"1"1"1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf   (   :dM7( _ `bd}&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf%P{!IqHs 3\/&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf/\1[!V'].d4e&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfeg-bJ; o    !?!t!!!"H"~"""#D#&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfD#x###$E$y$$$'%Y%%%%%&q&&&'S'''(>(t((()L))&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf)))*K*}*** +T++++$,a,c,,,,<-n-p----A..../&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf/a///%0g000-1n11142t22253z334B4445F55566%6&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf+242i2t22222,353j3z3333454B4w444445<5555 666%6[6l6666777G7|777788G8W88888909e9v9999::.:?YLYZZ[[aaii(lFlttBzgz|h}j}}X~p~q~~ !hfB*CJ^JaJph!h= hfB* CJ^JaJphX%6l667G7778W888$909v99::.:_:::: ;Q;;;;<E<v<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfv<<< =7=h====,>Z>>>>?L?}???@>@o@@@A3AaAAAA&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfA%BVBBBBCHCyCCC D:DkDDDD,E]EEEEFOF}FFFGAGoG&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfoGGGH3HaHHHH%ISIIIIJHJvJJJ K:KhKKKK,LZLLLL&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfLMOM}MMMNANrNNNO3OdOOOO%PVPPPPQHQyQQQ R:RkR&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfkRRRR,S]SSSS!TOTTTTUDUrUUUV6VgVVVV(WYWWWW&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfWXKX|XXX Y=Y?YLYYYYZRZZZZZZ-[][[[[[\K\y\\&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf\\ ]:]k]]]]/^]^^^^!_R____`D`r````0aaaaab?b&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf?bpbbbc4cecccc#dTddddeFeweee f;fiffff-g^ggg&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfgghPhhhhiBisiiiiij8jjjjjj'kWkkkk&l(lFlll&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfll5msmmm$nbnnnoQooop@p{ppp/qjqqqr\rrrsTss&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfsstLtttttuFuvuuuvGv{vvvwAwtwww x=xrxxx y=y&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf=yryyyzgzzz {={t{{{|D|v||||}}h}j}}}T~W~p~~~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf~  !i)CEWK\^ad&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfIWd$G_`Ȅ$(;?^dΆ8mpڋ#Dq9_{”Jٗmp.MQgkޜ A8roΡ7a¦'=hfB*CJ^JaJph!h= hfB* CJ^JaJphX΃$&CF_Ȅʄ$;^`6Ά~Iƈ2&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf24mjlŊBڋ #Uҍ>@q!t&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdftߐDǑ35_ uwԓQJy{՗&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf՗mJMOlo (*MgCm؜ڜE&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfEAr͞24rikޠ:Ρ{Hƣ13a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfa}M"'^Ȩ79_ةSתJ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf=_ةתΫĬ­ǮүSɰͰ+/tӲVѴ0oոSv|+ i.2t[F~_4bhfB*CJ^JaJph!h= hfB* CJ^JaJphXΫ@Ĭ>­BǮFίѯSUo&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfoɰ+t^ͲϲV<ѴC  0_i&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfikŷgϸѸTMOvvۻݻPvxҽJ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf+b{} i2~.t]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfM[@BxzH V&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf_a{M.0bE:.&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfTv\u $f3>b$~Pc Ogf~12JDW axyFavhfB*CJ^JaJph!h= hfB* CJ^JaJphX*,.Tru&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf\Y[u $bce3v1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf1;=b$a!{}MOc R&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfRLNgcce~1y+x&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfxz}/1J@ACW U&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf ^`xCEae$su,.J&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfv/J@AWi+Bp!67vwo$A>SV7RPk*BC\s]t (12OghhfB*CJ^JaJph!h= hfB* CJ^JaJphX@TVi7(*B"mo&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfo 6vln!#A1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf!;=Sr:46RE&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfMOk&)B Y[s] Z&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfZ\t  (l1{2z),KNg3&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfh/H~    F g  r s         ,|Jb =SJg 'z4Nby.zKcd    V!l!!""hfB*CJ^JaJph!h= hfB* CJ^JaJphX3,.H- { }   K     C E g    r  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf   R     ,q K,s\p&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf|~DFb ;79S$&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfDFg'gtv.0NE&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf\^y.dtv%(*GJc &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf  K     P!R!l!!!!"9"""""9#;#R#~####!$}$$$&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf""?#R###$$%1%%%%y&&&&'''U(q())))P*i**O+S+l++,,,S-f--...9////>0Q00011!22222]3333l4452555n667-7777z888J9d99:::B;Z;;<<<E=hfB*CJ^JaJph!h= hfB* CJ^JaJphX$$%%1%_%%%%%%%%y&{&&&&'D'''''O(Q(q((((&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf()D)))))J*L*i****O+l++++,F,,,,,M-O-f----&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf-.5.....6/8////80:0Q00000$111112222_222&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf222Z3\3334f4h4445525a55556h6j66677-7Y777&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf777777z8|88888D9F9d9999:>:::::<;>;Z;;;;&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf;<-<<<<<?=A=Y====>H>>>>>\?^?y??@@.@d@@@@&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfE=Y==>>>b?y?@.@@@AA9BWBBCCCnDD-EKEEFFFbGGAHYHZHHHIIIFJ`JJKKKfL|LM0MMM{NN+OAOOOPPVQfQQRRR_SrSTTTTCUXUUUVV7WFWWWtXX4Y>YYYXZjZZhfB*CJ^JaJph!h= hfB* CJ^JaJphX@A{A}AAA3B5BWBBBBCJCCCC DhDjDDD'E)EKEEEEF>F&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf>FFFFF\G^GGGHH H=H@HYHHHHHI@IIIII@JBJ`JJJ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfJJKJKKKKL`LbL|LLMM0MfMMMMNuNwNNN%O'OAOOOO&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfOO;PPPPPPQRQfQQQQRMRRRRRYS[SrSSSST=TTTT&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfTT=U?UXUUUUU.VVVVV1W3WFWpWWWWXnXpXXXYYY0Y&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf0Y3Y>YYYYUZWZjZZZZ[[[[\!\;\=\\\\>]@]X]]]]]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfZZ[mn/n0nnnnwoop2ppp`qsqrrrrbs{st7tttuu@ZWҌ#ۍ68S&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf`Ïy{ egՑ13KP&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfѓrtDFe'iŖǖ%җ-/K&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf $ؙik̚(*H>&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf[]}Ν*,LjƟȟ;dfӡ13L&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfRӣ֣lnOQuƥ"$DX&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfҧ;Q_p %&Ƭbv0ݯe%@Ha µܵ4Xt3ո;TϻoA\)ؾWx+EJp~hfB*CJ^JaJph!h= hfB* CJ^JaJphXҧ#ڨ57QIY[p  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf %¬4\^v0{ׯٯA_&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf_añ!@ܲ޲:BDa `ܵvx&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfx{}46PRTt3sϸѸ-ڹ57T&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfSϻ ik߼;=\  )wҾԾ0QS&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfSx%'EL`JLfh~n&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf;y{%ce(bd~!ce&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfm (bmt"{oPf!9!{.h4!<.0Kh M23PchfB*CJ^JaJph!h= hfB* CJ^JaJphX(jl"l/qs KNknS&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf FHf9!\WZwz  .&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf.^`4&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfJ <DI.u&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfu-/K)eg Mz2&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf2 MOc UGIa]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf JaPeRi\s "'F`d$ZlBV+:%^o,Cb|BZ*hfB*CJ^JaJph!h= hfB* CJ^JaJphX MOe\ OQieY[s&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf "o3')B`$&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf$VYl>AV%'*:c&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf%[]o,T6OCE^&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf^|>AZ&)7_68;&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf*7H[6L)fufw.B ?P$C]aLc(>nDZ 6h-A%_n=hfB*CJ^JaJph!h= hfB* CJ^JaJphX;=?ACG[25L)beu&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf^acew*-B{~ <>P&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf0$&?]IKc%'&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf'>kmACZ6eg&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfA%nJXZFH/1i&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf=J7XZ#BRP`Vg7LVe[!p!$$$C%b%p%^(n(l++...?/^/n/j2}25M6]6666`77Y8e88888 9-9c9w9999:;:W:::::*;F;z;;;;<6<j<<<< =hfB*CJ^JaJph!h= hfB* CJ^JaJphXQ  > {    / i     X     D |    ) c &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfc    Y F6rtv#%?AR &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfk+KMO`v4QSUg#%&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfEhk46L  g*QSU&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfUe{9    V!X!Z!p!!4"6"""#b###+$$$$$&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf$$$C%E%_%a%p%%&&(&&&&?''''Y([(](n((()*))))G**&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf**+g+i+k+++A,C,,- -d---(......?/A/[/]/n//(0*0&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf*0000G1112g2i2}22=3?3344e444*55555555M6Z6&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfZ6]66666677B7S7Z7\7^7`777748K8O8e888888888&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf8 999-9L9W9Y9w99999999:$:/:1:W:s:~:::::::;&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf;;;F;b;m;o;;;;;;< <<6<R<]<_<<<<<<<<<&=C=N=&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdf =&=[=x===>>R>`>>>>>*?8?l????@@P@[@@@@@@@*AAAuAAAAA&BZBiBDDDOEQEbEFFF}HHHIJRJyJKKKKKLLLLdMfMwM,N-N.NOOOQQQRRRhfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph!h= hfB* CJ^JaJphON=P=x========>:>E>G>`>|>>>>>>>>???8?T?_?a?&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfa?????????@8@C@E@[@n@y@|@@@@@@@@@@AAAAA&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfAA]AhAjAAAAAAAAA&BBBMBOBiBBB C2CDCCD D?DADODSDD&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdfDDDDDDDEEEKEMEQEbEdEEEEEEEEFFFFFFFF&1 a 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 &a &1 &1 &1gdfF8GGGGG$H{HHHHHHIIFIhIlIIIIIIJyJJJK KK &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfKKKNKRK}KKKKKKLL!L#LKLNLLLLLLLLL#M&M4M`MbMa1111111111111111a111111gdfbMfMwMyMMMMMMM N(N+N,N-NANENNNNNO]OyOOOOOOO11111111111 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdfOOOPPPPP Q"QQQQQQQQRRURXRiRRRRRRRRR &1 &1 &1 &1 &1 &1 &1 &1 &1 &1a111111111111111gdfRRS S"SASDSESFSXS\SSSSS T T0T3T5TTTTTTTTU"UKU111110%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdfRESFSGSSS TTUUUUVVVWWXX~XmYYZ(Z\[][^[\\?\\\\^^^_____aaaAbVbbbbqcddddddd;e!h=&h@AB* CJ^JaJphh[g B* CJ^JaJph h@A5>* h[g 5>*hFqh}hf!h= hfB* CJ^JaJphhfB* CJ^JaJphhfB*^JphhfB*CJ^JaJph8KUVUUUUUUUUUUUU|@|B|D|_|b||}}+}/}|}}~]~~~~~=TWY[(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd@A[]Tb€HTWY[]^_Ӂف#y˂(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1&a&1&1&1&1&1&1&1gd@Ac^_`}V?\G,?DxL|f,XB[Cۓ {Ɣ7HחEGj٘› 2GIh@AB* CJ^JaJphh@AB*^Jphh@AB*CJ^JaJph!h=&h@AB* CJ^JaJphO˂m}҃K{}ԄVZbf&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@A?AG{ˇ?ACx HL&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@AL|݉=:@39&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@AČX[.4lrȎek̏9|ܐ)@&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A@B[]qڑ-Lvxzē  {}Ɣ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A0360kvzH[֗EGjlnјԘؘ֘ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@Aؘ*,.0246rt09`c›  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A 0G,2GY_dAF6;z &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@AA6ez>`F 9 HiӤ;ͥDoBptө*.s@Efq6]ercRTܰ;i!h=&h@AB* CJ^JaJphh@AB*CJ^JaJphX`uF9lأHͥ٥ޥ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@Aޥ ?Co*hpI.9>Aos &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@As@Ef]brZ`ҮPVR &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@Aiұֱ@bn(TZóERXB'279^b &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@AiֱóAEZm̵#'bR_n.]»UyѽսD6Zs8N9!KOq=PBO!h=&h@AB* CJ^JaJphh@AB*CJ^JaJphXb&,Yfmɷշ/;_lܸ,x}6; &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A;CH*.]»ٻ5:üƼUս &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@ADiɿο6, &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A,/:.2:=gqN &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@AN[9V;@bg!O]bortvx &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A #%CFr4AE59 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A!:So?anp7;HM &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@AB[ins@_ )G|M &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A#/[GS|%>AZ\ui5rw'wxy6Bt/3Y<=>M 8U$h@AB* CJ^JaJphh@AB*^Jph!h=&h@AB* CJ^JaJphh@AB*CJ^JaJphO-BH/GMav|[ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A[_9Pf Skq?r>RZ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@AZuy $Znv?u &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A .4z ik&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1(agd@A\brtv')+oqsvwx(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1x(agd@A.46tv9?x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1 &a &1 &1 &1 &1 &1gd@A/1V\}HY &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1&1&1&1gd@AY[ort68;<=I=MOi&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gd@Ai*}8:&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@A 0Rhjl.5KNk2P=@BCD&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &agd@A$2=CDEZ&hy.0GImotO}!M;S  #$9:VWqrh@AB* CJ^JaJphh@AB*^Jphh@AB*CJ^JaJph!h=&h@AB* CJ^JaJphODIZ\psuw&(y{ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A.GmPVpvetv &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd@AO>rP7;(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd@A;=?AHNhn!#7:<ILS(1(1(1(1(1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd@A #9Vqio &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1(a(1(1(1(1(1(1(1(1(1(1(1(1gd@Ap |     0 ^    j k l   9E"Yt8LOy|.0XZT&fwACcSf!h=&h@AB* CJ^JaJphh@AB* CJ^JaJphh@AB*^Jphh@AB*CJ^JaJphOp          a g      0 2 F I K X [ ]   (1(1(1(1(1(1(1(1(1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd@A ! b d f i j k     0 6           9(1(1(1(1x(ax(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1gd@A"$tv357LNy{.X 28x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1 &a &1 &1 &1gd@A8TVo#=Csy &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1gd@A   !#%fhj &z &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1(a(1(1(1(1gd@Az #WY[AcgSW)(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd@Af)4rRzwxv  j!!"#d#g#h#i#####$D&r&l(m(n(((࿸shP{B* CJ^JaJphhP{B*^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJph hP{5>* hFq5>* h}5>*hh,h@AaJh@AB* CJ^JaJphh@AB*^Jphh@AB*CJ^JaJph!h=&h@AB* CJ^JaJph-)-/13r*0QW  468:<ILPz~(1(1(1(1(1(1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@A<BDqsvwxD&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1&1gd@ADJ" Y [        !B!F!!!!!!!!."&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd@A."2"9"="U"a"""""""##d#g#h#########$:$k$&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&&1&1&1&1&1&1&1&1&1gdP{gd}gd@Agd@Ak$$$$ %%%%]%`%%%<&A&r&&&2'8'c'm'''''''''(&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{(#(d(h(k(l(m((((((((()1)6)n))))***#*&*M***&1&1&10%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdP{(((4)6)*+++\,^,,-$....q/s/1&2e<k<<0=zE{E|EEESGJJJ/K1KKLMMMhNNROlOOOOOOPPQQQQOR8T9T:ThTjTUUkVmVIWWWXYYZY[YYhhP{B* ^JphhP{B* CJ^JaJphhP{B*^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphJ**+M+T+V+++++++++",%,Z,^,p,,,,,--#-&---$.0%10%10%10%10%10%10%10%1x(ax(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1gdP{$.O.S.U......../ /-/o/s///M000p11112"2$2&2q2x(1x(1x(1x(1x(1x(1x(1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{q222233@3l3n3p3}3336444>5B5i5555$6)6D6M6n666.7&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{.7a7h7777#8*80898?8888.9L999993:::X::::;;N;V;&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{V;y;;;;;<"<.<5<^<g<<<<<<<<"=)=,=.=0={====>=>&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{=>p>>>>>>>? ? ?,????? @ @Q@o@q@@@@@A-AfAqAvA&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{vAAA/BTB_BdBBBBCCCC!C$C&C(CMCxC{CC.DdDDDD7EOErE&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{rEvEyEzE{EEEEEEEEhFFFGSGUGnGpG~GGGG]HbHHHHH&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{HIIIOIyIIIIIIJJ=JCJHJOJQJJJJJJJJJJ-K1KCK &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1gdP{CKoKKKKKKL/LFLHLJLWLZLxLLLMJMNMMMMMM#NeNgNNN&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{NN?OJONOQOlOOOOOOOOOOPPHPePuPPPPPQ6Q[QzQQ&1&1&1&1&1&1&1p!ap!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1gdP{QQQ1RORQRjRlRyR|RRRSS>SIStSSSSSSSS-T4T7T8T9TLTp!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1&agdP{LTPTfTjT|TTTUBU{UUUUV+V/V1VgViVmVVVVWIWKWdWWWW&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{WWWWX*X,XEXGXfXiXsXXXXXXXYZYYZ!ZmZoZsZZZ[[&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{YYZoZ[\+\/\\\]\\f]]]]^^^_^_r_aaaaaMbQbbbbbcbccfeeee,fmffff gggh]hhh iiNiiijkl*mUmm nnnn)o+oq"rrrs ssssssthP{B* CJ^JaJphhP{B*^Jph!hhP{B* CJ^JaJphhP{B*CJ^JaJphO[ [N[P[s[~[[[[[[[[\+\\\\\\]]]]]:]<]Y]`]]]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{]] ^%^g^m^^^^^^_r_t_____.`=`a``````````&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{``aaaaMbbbc.c5cHccccccc*d5dCdNddddBeQe\e^e&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{^eeef&f(fmffff gg?gAgZgagygggg]hhhhhhiiKii&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{iiij j*jjjrjjjjkCkLkNkkkkl'l/lxllllmmmm m&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{ m"mUmmm nnnSn^nnnnnnnnnnn'o+o=ooo2pjpp>qq&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{qqqqqqrrr!rrsssssssstt|tt8u=uuuuuu&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{t|tttt8ubvvw=xxxx2yyQzzY{|||}}}}}}}}+~-~EAgŃ(SQɅͅ;?{|†XY'j JdƉ,qȊhP{B* CJ^JaJphhP{B*^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphOuvvXv^vvvwwLwTw~wwww=xxxxx2yyyyyyQzzY{c{l{&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{l{{{{|(|0|7|=|B|F|I|L||||||||||}}}}0}2}?}B}&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1%a%1%1%1%1%1%1%1%1%1gdP{B}d}}}}}}}}~~)~-~?~q~~~#bK̀%1%1%1%1%1%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdP{&Eʁ΁?CFHJWZAdf"%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdP{"$S݄AGMɅ;{X!%j%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdP{ DFd‰,kmȊ 36h%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1 &a &1 &1 &1 &1gdP{ȊjlcLՏ5Merf{֓ޓ&<D~ȔPciܖLƗ ҤԤĥ_bئ&Ԫ֫Ϯ(ȲʲhjProȻhhP{B* ^Jph!hhP{B* CJ^JaJphhP{B* CJ^JaJphhP{B*^JphhP{B*CJ^JaJphJhl~*bŌce͍ύLrvώ2e &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{MԐ'Yȑ͑.br~Ē &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{Z^{֓<~.3h ,Ncg &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{&)DLw͘#gəQtG &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{"19b~=Ga$,<ELRW[uz &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{v|#c'/6<AEHԡ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1gdP{ 2y^ԣwҤԤ #T¥ĥ _b֦ئ§&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{§$$&kϩrԪ(r֫=KìM&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{M{׭:oͮѮޮ$(aů7;?}˰ٰݰ)&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{)7;zƱԱر$bptȲʲ/hjͳ4&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{4Ne|PRT׵MX]a#l&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{o˶ѷ.u1rwEĻ'0,=f;<=e {(D7ehP{B* CJ^JaJphhP{B*^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphOl÷uѸ (*,r%-Wbjnqsu&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{Ⱥ*1@CEĻ&IPƼ?w'9Xc&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{c),5xz'aX&i&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{,cgrvyAfmH&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{7;fDFSV')A&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{AETXZ-0257:;<J =[x &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1a1111111111111gdP{@GX_a Luw8Zes11111111111111111111111111111gdP{s(`k1WLWv/at11111111111111111111111111111gdP{t2I\kvx3:lD|1111111111111111111111111111gdP{/3cV$W['Eb&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{7e'm,x6Yc&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{'+mq,0x|6:Y]cg+1tx'+imMQF-1_cim  KQhP{B*CJ^JaJph!hhP{B* CJ^JaJphX+-t'iahMF&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{-_i KM>@i8&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{>Dim8%)59?Cx IM6\`15UY_c.4mq;?qw<@qwhP{B*CJ^JaJph!hhP{B* CJ^JaJphX%5?xz| I+2\1U_.0&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{0m;qs<qs!XAdX&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{!%X\AEdhX\  <B[_GKae'/QU#SY4:rv|hP{B*CJ^JaJph!hhP{B* CJ^JaJphXX <>[Ga')+Q&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{SU46r|=b&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{28[_ei)-37gm@Fimsw:>D&*pt RVKghhP{B* ^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphR$foq24[e)3gi&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{@Bis:Da&pRKa&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{ac&-sz|~.5`&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1a11gdP{1567 =      E I n t     P T         1 5 ; ? }        L P s w }     AE\`z%)hP{B*^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphhP{B* CJ^JaJphO1456IM ;q.o111111&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{/3h:r = X Z v x      E n p  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{  P      1 ; }      L s }    A\9@ov&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{v%rls7Atv#%l&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{)rv 7;AEtz#)lp`dAE PX!%s48  -17;rvhP{B*CJ^JaJph!hhP{B* CJ^JaJphX`Aho PRT!s 4&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{4 -7rEIKIK0&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{ EIIOIO04]agk<@0 4 v |       !!3!7!g!k!!!!!!!"#"9"="n"t""""""""#)#-#hP{B*CJ^JaJph!hhP{B* CJ^JaJphX0]g<0 v x    !!3!g!!!!!"9"n"p"&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{p"""""##)#s#####+$-$^$h$$$$$ %%J%T%%%%%%&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{-#s#w#######+$1$^$b$h$l$$$$$$$ %%J%N%T%X%%%%%(((((( ))3)7)=)A)r)x)))))))** **?*E*h*l*r*v******+>+B+H+L+++++,,,<,a,e,,,,,--C-G-hP{B*CJ^JaJph!hhP{B* CJ^JaJphX%%%%&_&&&&:'''''>(G(I(((((( ) )3)=)r)t)))&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{)))* *?*A*h*r*****++>+H+++++++,,6,8,a,,,&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{,-C-K-j----:..../ /E////0!0#0%0_0a0000'1Z11&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{G-K-O-j-n-------:.>....../b2c2d2222 343~445"6j66777,8.8?8A8;;{<<<=;=A=======?>C>>>>> ????P?V???????@ @D@hP{B*^JphhP{B* CJ^JaJphhhP{B* ^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphJ112S2U2\2^2a2b2c2u2y222222 3 343V3334;4w4|4445&1&1&1&1&1&1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdP{5J555"6Y6f6666666666)7k77777777*8.8?8A8y8'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1&a&1&1&1&1&1&1gdP{y88888'9+9s9w999: :H:::::;;V;;;;;{<}<<<<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{<<<<= ==;=======?>>> ??P?R????@@D@N@@@@&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{D@H@N@R@@@@@@@A A3A9AAAAAAA B$BrBC"C&C,C0CYC_CCCCCDDTDXDD4EqEuEEEEEEEEF7F;FiFmFsFwFFFFF:G>GUGYG_GcGGGGG)H-H3H7HuH{HHH IIFIJIIEJJJJJJ!hhP{B* CJ^JaJphhP{B*CJ^JaJphX@@A3A5AAAA BrBBBBB"C,CYC[CCCDTDDDD)E0EqEEE&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{EEEE7FiFsFFFF:GUG_GGGG)H3HuHwHH IFIIII:JAJJJ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{JJJJJ.KmKKKJLQLLLLMMMYMMMMM5NTNNNNO?OzO&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{JJJJ.K2KmKqKKKKLLLM MM#MYM]MMMMMMMMM5N9NTNXNNNNNO O?OCOzO~OOOOO P P>PBPoPsPPPPP QQDQHQQQQQQQQQ+R/RbRfRRRRRSS7S;SyS}SSSSTTTWT!hhP{B* CJ^JaJphhP{B*CJ^JaJphXzOOOO P>PoPPPP QDQQQQQ+RbRRRS S S7SySSSTTWT&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{WT[TiTmTTTTTTT%U+U:U>UpUtUUUUUUU VV=VAVRVVVVVVVVV6WΰҰ%)w'+15^d!Y]9vzĴȴδҴ<@nrx|?ChP{B*CJ^JaJph!hhP{B* CJ^JaJphXҬDݭUWȮ  ISٯ 8:ΰ%wƱ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{Ʊͱ'1^`Y.5vĴδ<nx?&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{?Zd.8z|ηK?Fݹ߹3rOV&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{CZ^dh.28<zηҷKOJݹ37rvŻ "(^bļȼ:>Y]ҽֽ DH־ܾCGtxֿܿIMhP{B*CJ^JaJph!hhP{B* CJ^JaJphXV "$^ļ:Yҽ D־ؾCtֿؿ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{I0g <~\n')<r&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{04gk <@~ #\`n'-<@rv ?CTX8>w{%+W[aeKShP{B*CJ^JaJph!hhP{B* CJ^JaJphX ?T8:w%'Wa&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{KMOW3{} RTT^&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{TX^b%)/3bh28[_ei RX8<Z^:>BF 6:WXBDVihhP{B* ^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphS%/bd24[e RT&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{8Z:B 6$hoTV~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{~OHJQSVWX8>@D&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{VXehO+wbF8|Y &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdP{O>?@HIJ]_xzSm]abf&,lp$(ag ]aHhP{B* CJ^JaJphhP{B*^Jph!hhP{B* CJ^JaJphhP{B*CJ^JaJphO8:=>?UY}BDGHI]_ &1 &1a1111111111111&a&1&1&1&1&1&1gdP{USdhLuzV!SUm&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{]b&(l$ac&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{  ]H/1*|Gc&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{/5*.| GKcg ?CIM+/59tz  KQ n[_kouyCGl/3gkhP{B*CJ^JaJph!hhP{B* CJ^JaJphX ?I+5tv KMn[k&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{kuC 'ah/g *dfP&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{ *.djPTquEIrvW[8<w{ OS-1?CrxFJ}%)hP{B*CJ^JaJph!hhP{B* CJ^JaJphXPqErW8w O-&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{-?rtF}%Z\^  HR&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{)Zb HLRV(,26gm$%)/3ek39\`fj  , 0 6 : s y       # ) m q w      hP{B*CJ^JaJph!hhP{B* CJ^JaJphX(2gi (pLN#%W&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{%/eg35\f  , 6 s u   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{     # % m w     + u      W    P t v   9&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{ + / u y           W [       P z ()* }=CAE RX FJPT 5;hP{B* CJ^JaJphhhP{B* ^JphhP{B*CJ^JaJph!hhP{B* CJ^JaJphN9@%'O P"$'()>@BD|&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1gdP{|)-uy J X}&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{=?A RT FP&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{57"t$.[]V+2s&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{"&t$(.2[aVZ6sw9=kouy< @ W [ a e     +!/!5!9!w!}!!! ""H"L""G#########0$4$o$s$$$$%%% & &&!hhP{B* CJ^JaJphhP{B*CJ^JaJphX9ku< W a    +!5!w!y!! "H""""<#C###&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{#####0$o$$$L%S%%%% &&!&[&&&&&7'V'''' (A(|(&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{&%&[&_&&&&&&&&'7';'V'Z''''' ( (A(E(|(((((( ))@)D)q)u))))) **F*J*********-+1+d+h+++++ ,,9,=,{,,,,--- -Y-]-k-o-------'.-.<.@.r.v..!hhP{B* CJ^JaJphhP{B*CJ^JaJphX|(((( )@)q)))) *F*****-+d+++ , , ,9,{,,---Y-&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{Y-k-----'.).<.r..... /?/T//////80:0w000000&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{...... //?/C/T/X//////080>0w0{000000000%1+1W1[1a1e111111122K2S255T5X5^5b555555556$6(6.626a6g666666666.747W7[7a7e7777777 88N8!hhP{B* CJ^JaJphhP{B*CJ^JaJphX0%1'1W1a111112222K2M2O2W22233{3}33 4R4T44444&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{4555T5^5555555$6.6a6c6666666.707W7a77777&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{7 8 8 88N8P88888849V999996:>:::;2;{;;;;<V<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{N8T88888884989V9Z9999999996:::>:B:::::; ;2;6;{;;>>?@"@@@@A1ACAnA~AAAAABCDD EE1E2ECEEEEEESGGXHHSII1JJKKKLLLLLOhP{B*^JphhhP{B* ^Jph!hhP{B* CJ^JaJphhP{B*CJ^JaJphOV<]<<<<<<<=^=e===>B>>>>>>>>>>?^?a?o???&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1gdP{????"@8@:@<@g@i@k@x@{@@@@@@@A AAACAJALASA~AAA&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{AAAAAAAABBBEBsBwBBBCsC~CCCDWDDDDDDDD&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdP{DDDDE E"E)E+E.E0E1E2ECEEEEEEEEFFF.F1FJFFFFG&1&1&1&1&1&1&1&1&1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdP{G G GGGGGGGHHHH=IIINIRIIII JJJJJKJKKKK'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdP{KLLGLJLKL^LbLLLLLMMMMMMMMMN@NNNNNOAOEOzO'1'1'1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1gdP{zOOOOP/PLPPQQ Q!QOQjQlQQQQQQQRWRRRRSbSSSP#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1gdP{OOQ!QOQQQQRRWR[RRRRRSSbSfSSSSSSS T$TCTGTMTQTTTTTTTUU^UbUUUUUUUVVSVWVnVrVVVVWWWWWWW7X;XXXXXXX0YYYYZZIZMZSZWZZZZZZZZ!hhP{B* CJ^JaJphhP{B*CJ^JaJphXSSS TCTMTTTTTUU^UUUUUVSVnVVVKWRWWWWWWWP#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1gdP{W7XXXX0Y~YYYYYZIZSZZZZZZ5[7[~[[[[(\*\r\\\P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1gdP{Z[5[;[~[[[[[[[[(\.\r\v\\\\\\]S]W]]]]]"^^___#_)_g_____0`4``aCaGaaaaaaabbN˺h-dB* CJ^JaJphh-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJph h-d5>* hFq5>* h}5>*!hVhP{B* CJ^JaJphhP{B*CJ^JaJph:{{|||C|G|[|]||||||}})}.}>}B}I}M}^}b}e}f}g}~}}} a 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 a 1 1gd-d}}}}}}~~&~g~j~~~~~~~~~~~~~~-/SV 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1P#aP#1P#1P#1P#1P#1P#1P#1gd-dVqt $(9=@ABTX@7Y\P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d\‚?BEg}у%Thz΄ Nb &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dbsƅ07yΆՆ׆ȇ̇ۇ݇ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1"a"1"1"1"1"1"1gd-dۇabcƉȉps1ǍՍ,5CO `kɐ)|ۑHVgqĕЕ%.AK ]i=>?*Śך7h-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJphh-dB* CJ^JaJphO݇-0W48HL]`abuyƉ"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1@$a@$1@$1gd-dƉȉ$B`'Hps<@@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$10%a0%10%10%1gd-d 13X[]Ս5_sҎ/O|׏0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd-d׏ 8Lkɐ)WkǑ(/1_f|0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd-dђՒ8ٓܓޓ-4V?Sq%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-dЕ.XlΖ-Kvٗ 5Ii%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-d 29<=>TX*,QTVxך#L%1%1%1%1%1%10%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd-d7LX(ǜ ;cvםK_؞@Kğ+Ѡ Dm~ޡEW   WYȤjxϥإ*5GPbl̨*~^_h-dB* CJ^JaJphh-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJphO(]qǜۜ;OvÝ#7_؞+K|0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd-d+`tѠ DX~ɡ0W  0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1%agd-d 9=UYgȤʤ"68OVxإ5au%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-dҦ3Pzۧ:Nl̨*Vj˩ҩԩ%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-d$+5<SZ]^_rvƪswګܫ+2<C`%1%1%1%1%1%1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d_`uw,-.24 <>K    ȸ   jMV',cp#4LY$%&WXY789D_xYh-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJphh-dB* CJ^JaJphO`ɬ &(+,-@Dӭ04A9<>`n &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-dد߯#KVڰ u:>KM{~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d~,T_ijڳG  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1&1&1gd-d KNPrtCNɶԶ    $&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1gd-d$(Ʒ̷ҷ޷ Scou| &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dȸʸ̸CjŹɹ26RVuyĺ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d )-PTnrλһ15TXvz¼ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d +/KOnr½ƽ48^bھ޾  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d $(FJim%)FJjn]ahl &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d #r-DQ]jy C8 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d80CUgx8s@&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d@jm1HJLV{6:ei&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d(,Z^ $OSx'X\&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d=Anr@Dhl&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-dLPw{"&SW|(,Y]&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d ,\`FJ}u&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1$a$1$1$1$1$1$1gd-d02HOp4bv$8Y$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd-d   #$%9> (+WZy)-=A$1$1$1$1$1$10%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd-dACSVWXei3678tx;z 0%10%10%a0%10%10%10%10%10%10%10%1$a$1$1$1$1$1$1$1$1$1$1$1gd-d%DF_xOUXYZ0u$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$a$1$1$1$1$1$1$1gd-dYZ[  ?u=>? L{/H!xy3   2JKL9;hACRcdWGHIqsmh-dB*CJ^JaJph!hh,h-dB* CJ^JaJphh-dB* CJ^JaJphh-dB*^JphO  ?AXu:pr9<=>~$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1 &a &1 &1 &1gd-d^ j(+FJ{/[ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dknpC$a$1$1$1$1$1$1$1$1$1$1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dHJce x.2  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d  !V2{ NQy2FIJKa&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1%agd-dae7;HhjN?CRTW%1%1%1%1%1%1%1%1%1%1%1%1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d 9IK[^`bcd,d <V&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dVXZ\(*LPgtxz &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1gd-d.4GWYv-/CF&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-dFGH2osY\~QS &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d`gi368Z\ &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1xax1x1gd-d}~57D  &      lq41G`a kmjrstvx   0#2#3$A'B'C'**A+j-k-l-../11!hh,h-dB* CJ^JaJphh-dB* CJ^JaJphh-dB*^Jphh-dB*CJ^JaJphO!JMy|}~37FhDFbdx1x1x1x1x1x1x1x1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d  & ( C F H j l          d ~    , r $a$1$1$1$1$1$1$1$1$1$1$1$1$1$1 &a &1 &1 &1 &1 &1 &1 &1 &1gd-dr     - S z    D      Bln :4 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d4bi$+-G\_`a"(y )+Y\ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d\im} ,0 &1 &1 &1"a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1 &a &1 &1 &1gd-d>@N\gz "6FR`kx &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d02bfvz &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-dY^Kc~"jl*-AE&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-dEmqx| <AEHnqrstx &1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d  $ m      !!.!i!! "w"".#2#?#{##$3$5$R$k$m$$$ &1 &1 &1 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-d$$]%c%%%%%%;&B&&&&&&&&'='@'A'B''''''N((&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1gd-d((U))**!*]***+A+C+\+y+{+++,e,k,,,,R-f-i-j-k-- &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1%agd-d----.D.....9/l//////6090q000:1U1\1o1v1111%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-d111111111 2 23262V2~222222223 33 3R3T3~33%1@a@1@1@1@1@1@1@1@1@1&a&1&1&1&1&1&1&1&1&1&1&1gd-d1111 2222 33R33354b4f44445557718|88::;:<:;<<<<N=O=P=>>-?????V@W@X@AAACBDBEBYC[ClCDDDD*G+GyH{HHI"K$K8KKKMMMMMM NNh-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJphh-dB* CJ^JaJphO333b4e4444#5'595j5z5555555556 66h66 7o777&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd-d771838L8N8x8{8889+9.9[9_99999999 :":6:9:::;:[:`: &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1x(ax(1gd-d`:::::3;u;;;<<<0<G<I<q<t<<<<<<<====J=M=N=x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1x(1gd-dN=O=}==>>>P>>>>?-?/?d?g?y?{?????????(@,@.@R@%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd-dR@U@V@W@h@l@@AGA[AoAAAAAAAABB(B=B@BBBCBDBWB[BBB &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1&a&1&1&1gd-dBWC[ClCnCCCCCCCCDD`DgDiDDD+E-E]EEEE+F]FFFFF&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd-dFGG$G&G)G*G+GBGFGZGGG+H@HwH{HHHHHHIIIBIFIIII&1&1&1&1"a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1%1%1%1%1%1gd-dIIJgJJJJ K$K8K;KjKmKKKKKKKKKK* h}5>*hh,h-daJh-dB* CJ^JaJphh-dB*^Jphh-dB*CJ^JaJph!hh,h-dB* CJ^JaJph,QO\OoOOOOOOOOOO PP*P:PFPTP_PlP}PPPPPPPPPQ8181818181818181818181818181818181818181818181818181818181gd-dQ Q&Q(QVQYQxQQQQQQQQRRRRRRFRJRRRRRRRR S81818181818181818181818181818181"a"1"1"1"1"1"1"1"1"1"1gd-d SS"S5SHSYSkSzSSSSSSSSST TT%T2TCTYTkTvTTTTTT"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd-dTTTTTU"UAUmUpUUUUUUUUUUUUUQVSVcVVVVVV"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1`"a`"1`"1`"1`"1`"1`"1`"1`"1gd-dVVV'W*WbWhWWWWWWWWWWWWWXX$X&XAXDXOXnXXXX`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1a11111111111gd-dXXXXXXX$YMYQYbYoYrYYYYYYYYY'Z,Z@ZNZRZtZZ1111111111xax1x1x1x1x1x1x1x1x1x1x1gd:R;gd}gd-dgd-dZZZ[[[Q[w[~[[[[[[[[[[[[[!\#\S\W\j\l\n\x1x1x1x1x1x1x1x1x1x1x1 a  1 1 1 1 1 1 1 1 1gd}gd-dgd:R;gd:R;W\j\\\\[]]]p]]]]^^0^F^^~______```napaa\c]c^ccccdddddddffgygghFhijjjllllll&m'mmmmnnnoo1o~ooooogpip|pqh3B* CJ^JaJphh:R;B*^Jphh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJphMn\{\~\\\\\\]]'])]Y]]]p]r]t]]]]]]]]]]]^^0^ 1 1 1 1a11111111111P#aP#1P#1P#1P#1P#1P#1gd:R;0^2^F^J^]^`^^^^^^^^^_2_G_z_}_~__________*`P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#1P#aP#1P#1P#1P#1P#1P#1P#1P#1gd:R;*`@`C`E`^`a`````````:az|u}w}6i;ɻӭӦ!h2khOdB* CJ^JaJphhOd hq5>* h}5>*h+dB*CJ^JaJphh:R;B* CJ^JaJphh:R;B*^Jphh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJph h:R;5>* hFq5>*5OsQsssss"thtltotptqttttu uuRuUuluou|uuuuuv v7v&1&1&1&1&1&1&1&1$a$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd:R;7vmvqvvvwpwtwwwxwywwwwwztzxzzzz-{2{E{{{{||&|y||||||||}s}(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1&1&1&1&1gd:R;s}w}}}}7~]~~~.b6Ni&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;;;ƃʃU-Ds&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdgdOdgd:R;gd:R;kmcԊ `l4ē .:Niԗ4OotG{>BwReg֛PX V ɣ /\67AKrߪ!h2khOdB* CJ^JaJphhOdB*CJ^JaJphXs̆,ckmω݉3_acԊ֊<͋&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd͋ϋ"oq)D|~  ?iŎ `ޏ)Rhj&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdjlPSÑƑȑAtwy{’Œ4&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdVagʔΔє  .z}ەޕ:J&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdJMiԗ3OjmotGz>wM&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdMPReg֛4VZ P%QT&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdTVXڟݟߟCF ;NQTV<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd<m ɣ /nqߤ*,=Wҥإޥ61&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd1ȧA}ʨ #FIKթةHq&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdߪ8|W\^`58gحڭݭ7&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdߪ8٫'W`حݭBD*,ذбó޳imi߸2GPjغ/R.w7NQ*dJb,B&hOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphT:>@Dد*,ذOu|бLR`f&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1gdOdFóܳ޳il4µ8@jǷ&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd2eG޹j"b/\Rrڽ#V&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdV˾Yп.NQEtdbB~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd<t#0HWMP^&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd&<^Xo-3I9+J\}|KNrY;%9@ ++/p vGn?Pi;whOdB*CJ^JaJph!h2khOdB* CJ^JaJphX'?WbjSVXo-3_jny6adf&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdf%IL:>9~<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdJMT JSWZ\}0AEim:KO&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdOqu@RVk|&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdyAf% |=KMr)&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdTWY?h:48;$BC%&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdP9<>@ ?Bs+ux&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd$')+ /cf.1G|b~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd,/ e fh  JM GXgjln&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd :=?&1f  BEGIlo3>B&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdBim+6:w* , . 9 s        # &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1$agdOd* .    f h    A  O e         ! 1 6 D 4 H 8 I : P l          " " % % ( ( + + / / / / / / / / 40 L0 P0 0 0 !1 Y1 v1 1 1 1 %2 X2 {2 2 %3 hOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphO# ' d h t     ? A        e     8 n    K g $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOdg i       & B \      & ^ z     2 N g $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd / > X ~  8 T m % \ x  1 $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd1 U d ~   6 ] y      1 J q        D h w $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOdw      / I o      % A Z         H l {   $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd    3 M s      ) E ^         I m |     $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd  4 N t      * F _        & ( w        $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd  P     # Y    6 R T l s      - G n      $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd ' C \       ; W f z |      0 J q ! *! F! $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOdF! _! ! ! ! ! ! " >" Z" i" }" " " " " " # 4# N# t# # # # # $ -$ I$ b$ $ $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd$ $ $ $ % % A% ]% l% % % % % % % & 9& S& y& & & & & ' 0' L' e' ' ' ' $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd' ' ( ( A( ]( l( ( ( ( ( ( ( ) :) T) z) ) ) ) ) * 1* M* f* * * * * + $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOd+ + B+ ^+ m+ + + + + + + , ;, U, {, , , , , - 2- N- g- - - - - . . C. $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gdOdC. _. n. . . . . / / 8/ ;/ > ? ? ? A ZA LD jD D D D @E BE E E E F 9F ZF F F F F dG G G H H H I I &J J J "K aK K 6L KL oL %M LM M M N EP hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphO14 J4 N4 4 4 4 5 25 55 75 T5 n5 q5 5 5 N6 6 6 6 6 6 6 6 7 77 :7 <7 7 7 7 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd7 7 7 8 8 /8 48 a8 8 9 T9 Z9 9 9 9 9 9 9 9 : : : : F: Z: ]: _: : : : &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd: : : #; X; u; y; |; }; ~; ; ; ; ; ; ; ; < ;< d< < < < = F= `= b= u= x= = &1&1&1&1&1&1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd= = "> o> > > > ? 4? z? ? ? ? @ U@ W@ Z@ \@ @ @ @ @ A ZA kA nA pA A A A '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdA B 8B XB B B B B B B =C C C C D ED HD JD LD jD D D D D D D D D D D '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdD D D D D D >E BE SE E E E 9F F F F F "G 1G dG G G H +H :H H H H H I &a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdI ?I BI yI I I I I I I I &J fJ iJ J J J J J J K K "K MK aK K K K K K &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdK K L 6L DL GL oL L L L L M LM ~M M M M N 7N BN PN jN qN sN uN N N N N 6O &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd6O eO O O O O P !P #P

h i ?i Vi mi oi i i i i $j rj j *l Dl m m )n Zn Mo hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphOR R R R R R R R R R 3S S mT T U nU U U U U U U 2V hV jV xV V V W FW &1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdFW W W W W W FX X X 2Y eY Y Y Z XZ Z Z I[ v[ [ [ [ [ ?\ q\ \ \ \ ] []  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd[] ] ] ] (^ +^ ^ ^ ^ /_ 1_ M_ q_ s_ _ _ _ ` N` ` ` ` a >a @a a a a a Nb  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdNb b b b b b )c uc c c c #d %d cd d d e e Ue ne e e e e +f .f Xf Zf {f f  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdf f f f f f f f g g ?g Bg \g `g g g g g g g g g g g g >h h h h h  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdh h i i ?i Pi Ti mi i i i i i i i i $j ]j bj jj oj j j j j j j j j k  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdk k Qk k k k k k k k k l l %l (l *l Dl vl yl l l l l l l l m 7m [m pm  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdpm tm m m m m m m "n %n 'n )n Zn n n n n n n n o 'o Ko o o o p Cp ]p bp  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdMo o o p p p q q r Ir 'u u K{ { { { H| | ~ G  2  u 8 K y  : H ~ |  d  Ŋ h  э   ܎  X D j  Ғ  D Ք Ɩ C x F  > | ! W %  H  L hOdB*CJ^JaJph!h2khOdB* CJ^JaJphXbp fp p p p p p p 4q 6q \q cq q q q q r r r r r Ir pr sr r r r r s Es  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdEs Js zs s s s s s t t t t t ut xt t t t t %u u u u u u u u u #v &v  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd&v zv v w bw w w w w x x *x bx x x x x y y y y y y y gy jy y z bz z  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdz { { { { G{ J{ { { { { { A| D| F| H| | | } } =} p} } } } } } ~ 5~ 7~  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd7~ M~ ~ ~ ~  G       2 ܀ ߀  a d  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd  @ B n p   p s u Ń ك    # 0 [ t y ΄  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd΄ Ԅ ܄ . 3 6 K p t w y 1 H L     : g j  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd  ? C F H ~ ܈ ߈ > | ȉ  ) - ^ b   &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd Ŋ  b i o x ~ ׋ ۋ ދ  h ̌ ό  < l  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdl p э  u { Ў ׎  0 9 ? ŏ ˏ    H M R  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdR U X Ґ Ԑ  > B j ‘    u Ғ   D  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdD g ֓ ٓ 9 = R  Ք ה ٔ  A q Õ  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdÕ ƕ  * I r Ė Ɩ  C t w " @ D   > r x  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd = D s ͚ Ԛ ښ ߚ     ! ` ܛ ߛ W Y % _ b  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdb  H } Ҟ ֞ ݞ    G ՟ ؟  G K   &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdL 9 k k  9   U W \ ݮ ) S b ΰ 2 N ߴ 0 O  R Ŷ ֶ  2 d u ܷ  g 5 _ $ b Ӻ  + { z R m 8 V % I hOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphO    4 7 9 k  k  9 y | J  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd     2 6 S W j E k  > ݧ >  T  &1 &1 &1 &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd & Y ( j ˬ  8 Z ϭ \ ^ z ۮ ݮ ) b d  P &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdP  p W " N O Q ~ R ֶ 2 u ܷ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdܷ ޷  g ٸ _ $  U ӻ $  { z  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd P R m  6 8 V   % I [ ^ j t } &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdI D g W   ( m i k < C q s  P > " ; } O H  Q \ !h2khOdB* CJ^JaJphhOdB*CJ^JaJphX % i  ~ 9 L  B D g W 9  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd G & s  $ p  t   ( Y ~ 1 s &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  @ i k m   A *  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  C  < d g C j &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd % 5 9 K N P R . A q s . 1 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd O R   I L b z }  O &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd I L i l   9 < > U X [ q &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdq " t x | I L ^ v ! # 7 : &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 6 g v y  G x < n p    &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 1 J L j . }   3 p ' ) F I K M O &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdO   N   w % @ Y w {  2 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd2 = z ~ ( + b d < C F H |  q t } &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   * 9 = J M O Q \   ( < > O x &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd\ t v  b g  v  \  k  \    ( Q n . V     ! R  )    l  V =  0 y   2    )# Z# \$ $ $ c% & 5& ' ' J) #* %* * Z+ n+ + , y. / / / |0 0 u1 1 4 75 6 6 !h2khOdB* CJ^JaJphhOdB*CJ^JaJphX ! D t v # S | #  . 0 6 ; z &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  : b e g   6 _ ~    u   $ &   1 3 [     d g &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdg i k    1 a    [   0 d f  q ( P : } &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd + n  @ B   / 1 Y [   ' * , . V    2 4  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  0 2 s     \ n      2 F j l     2 a     &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd     ! R   ) Z n   2   ~  l         l   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  V k     9       . y      . 1     4 ` &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd` 5! {! }! ! ! ?" " " " # $# '# )# Z# y# |# # # # &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd# # # $ 2$ G$ W$ Z$ \$ $ $ $ c% w% % % % & & & & & 5& N& Q& a& & & & ' &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd' B' a' ' ' ' "( L( N( z( ( ( ( ( ( 4) C) F) H) J) ) ) #* %* ]* * * * + /+ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd/+ 2+ H+ n+ r+ + + + + , z, }, , , , , , 9- D- f- - - - . 2. 9. [. t. w. y. &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdy. . / / / / / 0 0 [0 ^0 w0 z0 |0 0 $1 '1 ]1 r1 t1 1 1 1 2 (2 ,2 .2 2 2 2 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd2 2 2 G3 I3 3 3 3 3 3 3 3 H4 4 4 4 4 4 4 4 4 4 4 75 i5 l5 }5 5 5 5 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd5 5 6 #6 '6 G6 K6 R6 V6 6 6 S7 f7 7 7 7 7 7 7 X8 [8 8 8 8 8 8 V9 Y9 x9 {9 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd6 w7 7 7 7 9 9 %: o: s: : : ; ; < +> S> > > ? S@ U@ RB B B UC C 0D D D D D E uF F F F TG G G G #H 5H H H H I I I lJ J J K K K HL L M :N TN N N N N N N XO qO zO |O O P P P Q R S OT jT dU U V W /W X 9X _X X X !h2khOdB* CJ^JaJphhOdB*CJ^JaJphX{9 }9 9 9 9 9 9 !: o: : : : ; ; *; 1; g; {; ; ; ; ; ; ; < g< j< < < < &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd< < = = A= H= = = = = = = > > &> )> +> S> ~> > > > > > ? ? 2? [? _? z? &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdz? }? ? ? ? ? S@ U@ s@ @ @ A WA \A A RB B B B B QC C C C C C C C D +D &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd+D D D E E F rF tF F F G G G ,G :G PG SG G G G G H H H 5H eH H H H H &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdH I I ;I CI I I I I I J J HJ ZJ bJ fJ hJ J J J J J J J K ;K AK yK K K &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdK K K K K L L L L L L "M VM ZM \M :N PN SN N N N XO zO O O O O O O P &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdP P 'P 3P P P P P Q NQ {Q ~Q Q Q Q Q Q Q PR R R R R R R R S S S T &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdT 0T LT jT T T T T U *U .U 0U aU cU U V IV KV W (W +W -W /W aW mW W X 2X 5X _X &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd_X X X Y GY dY kY Y Y Y Y Y PZ Z Z Z [ [ [ [ H[ J[ w[ [ 0\ 2\ \ ] ] ] &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdX Y Y Z Z K[ w[ \ \ ] ] ^ F^ ^ ^ _ _ _ ` a a ,b Gb b b |c 3d d d e m m m Sn rn o p eq wq |q }q ~q 9w w w w 6x 8x ^x x x x x x y 4y ]y z z z { { | | U~ ~ B y  B / 0 hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphO] 7] C] ] ] ^ ^ F^ i^ ^ ^ _ N_ k_ r_ _ _ _ _ _ ` ` ` ` @a Ca Fa a a a &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOda b )b Gb b b b b b c c 2c 6c oc sc xc 3d d e e e Xe [e e e e e e e e &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOde e e f Sf f f f g dg g g +h h h i ai i i ?j j j +k yk k k k l Dl l &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdl l l @m m m m m m n n :n rn n n n n o *o Io fo o o o o p Cp }p p p &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdp (q `q cq eq wq {q |q }q q q q q q r 9r qr r #s Xs s Bt t t Ju u u +v {v v &1&1&1&1&1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdv 9w ;w Uw lw w w w w w w w 6x 8x ^x sx vx x x x y ]y ay cy y y z z Gz xz (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdxz zz z z z +{ K{ { { { { | r| | | | | } X} } } ~ U~ ~ ~ ~ ~ B w y (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdy     q    # ~  o B - / r (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd . 0 e   7 Æ ( * J }   ` b Ɉ ˈ R (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd0 e  7 Æ * J   b ˈ T r ɉ 3 | U ~  P x ʌ  < i ԍ  A 7 P T Ӗ   7  '  Ϡ  > A m r ̡ g { ͢ K ] A Ǥ  hOdB*CJ^JaJph!h2khOdB* CJ^JaJphXR T r ɉ 1 3 |  U | ~   P v x Ȍ ʌ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   < g i ҍ ԍ  = ? A 5 7 N P   P S Ñ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdÑ  I M P R  * / k p y ~ ݓ   7 : Y ` (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd` ֔ ޔ - 0 M P o v $ ) E M P R ͖ ϖ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdϖ  7 y { ' ^ e h j    _ ؙ   " N U (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd ߚ  H K ~ 9 h  @ l  ' X  B p (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdp ؟  C q Š ̠ > m p r ȡ ˡ # Q d f { Ţ ʢ  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   C H ] ƣ ȣ A Ǥ  1 6 s (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  K Ӧ ئ ) . 2 5 7 z   ! O  p (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd K 7  ! O u - ɪ į  . S ѳ ? x y 5 ׵ ( B } Ͷ  q u    C H R j l A r i A i  b L  g }  u U , /  hOdB*CJ^JaJph!h2khOdB* CJ^JaJphXp s u ީ   - n q Ī Ǫ ɪ  ] (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd Ĭ ߬ # ) , ^ d Э  |   7 g l p s į (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdį ' ) U Y Ѱ հ ذ  A D z | б ұ    (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd . o r ֲ ڲ   J N Q S ͳ г   8 < > x 5 B v y (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdy ҵ յ  % B s y ȶ $ , W ڷ ߷ q   (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd @ H M P j 8 < ? A r غ ں  J O u @ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd@ C k o ¼ T Y @ C g ˾ Ͼ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd * / 1 ` d g i  < ? A i    b (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   G J L  g < x { }   u (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd U z } / 4 j , O R (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd , 0 `   * b f / X [ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   Q z } + / 2 4 ' * K t * , (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd Q 4 *  i E h     O \       6 C p } # A l   @ 6    F c   i   @  =  J 0! ! z" " }# # h2khOdB* ^JphhOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphJ    s  U C (1(1(1(1(1(1(1(1(1(1(1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd   F 5 h  R T W 7 - 2 '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd2 4 3 r t N  4 6 j 2 e g '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdg   A   H J k & $ O Q w '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdw 9 ; = 2 5 7 . 1 k m  0 z '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd    _  c f  9 > \ '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd   " ' / 4 W    0 3 5 '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd % c f + S z    + . 0 O R x '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd 9 p s   7 < l  : T [ e l '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd 3 Q U j n p   N  4 8 ; = _ A '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdA u x z  @ D a   9 n 6 9 L ^ b m '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdm 0  r t U y . N '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdN r }  # X ^   / B F . |  '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd 8       6 n q      ! ] ` b     ) + G '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdG _ x       - N R Y ] v         B u x     '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd   , X   3 6    E H J i # & Z ] _ '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd  ! l  }  s    $ \    C }  '1'a'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd   e   =    ]    A       6 n p      @ '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd@ B k n  |  @ B  2 4   _   4 6 k       1 c g  '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd    J O S d g i  < ? a      @       =    '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd   J ! +! .! 0! ! $" '" E" u" x" z" " '# *# H# x# {# }# # $ $ 5$ n$ '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOdn$ $ $ $ -% F% H% ~% % % % % ?& B& d& & & & & '' *' L' ' ' ' ' ( ( '( ]( '1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1'1gdOd# % % & & ' ' b( ( .* /* 0* &+ (+ , @, R, U, 0 0 w1 }1 2 6 jL kL lL L L M (O Q \Q Q Q Q [R yR Y Z Z [ \ \ ^ ^ ^ ` ` px 5y py ry y y y } '} } }  _ Ȁ  J x 4 6 n h2khOdB* ^JphhOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphJ]( `( b( ( ) ) O) ) ) ** -* .* /* @* D* n* p* * "+ $+ (+ <+ L+ + + , !, >, @, R, '1'1'1'1'1'1'1'1'1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdR, U, , , , - 0- t- - - 0. t. . . K/ M/ P/ d/ / / /0 P0 0 0 0 0 0 0 E1 u1 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdu1 z1 }1 1 2 ?2 A2 o2 2 2 3 )3 Z3 3 3 3 #4 O4 ~4 4 4 5 95 j5 5 5 5 *6 ]6 6 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd6 6 6 6 6 6 7 7 37 ~7 7 %8 z8 8 8 8 >9 y9 {9 9 9 9 9 t: : A; ; ; ; < &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd< < f< < < < < < += .= K= O= = = = = -> 1> 4> 6> > > > > ? ? ? ? ? ? &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd? ? ? ? ? @ @ x@ |@ @ @ @ A A A TA WA tA xA A A A A lB pB sB uB B B B &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdB B B C C =C BC C C C C ;D @D cD kD oD rD tD vD xD D D D D D D 0E 3E ZE gE &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdgE iE E E E E E E E E E F F F F 'G kG }G G G G TH WH H H H H I JI MI &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdMI {I I I I I I I J 'J ,J /J CJ FJ HJ J J J J K v mv v w >w w w x Gx px rx tx x x x x x y (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdy y 5y Ry py ry y y y y y z 8z fz z z z { .{ 0{ O{ n{ { { { { | ,| R| {| (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd{| }| | | | | } } '} Z} } } '~ R~ ~ ~ ~  H w      * _ a (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  x 4 6 n Ղ D F  } W    D p ` e (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  D  Ɇ = ` ̇ ߈ 8 c ى " / [ ό ,  ͍ = G D ѕ  Z H  %  A s  , B > y  E I ̩ Щ  Ӫ լ Q , l w x Ͳ D * hOdB*CJ^JaJph!h2khOdB* CJ^JaJphXe ߈ c e " [ , z |  ͍ = G ( ^ u . n p (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  W 3 ѕ Z  E  ; u ڙ 9 i k ƚ @ ϛ ћ M (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdM O | ! # % Z z Ý   A } Ǟ  0 n ן 6 8 ۠  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  , ʡ : @ |  B D ٥ @ B > E G (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdG I ~ ̩ Ω Щ    F I { Ӫ   - _ q | ~ ۫ ߫ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  ' - S Z u | Ь Ӭ լ  Q ŭ ǭ ٭ ۭ  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd < @ j o     ' * , T . 1 g j l (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdl Ұ հ     > B q u ձ : ? U Z ^ ` s v x Ͳ ϲ V (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdV |  ʳ ͳ  = @ B ~ ʴ 5 D F { ~ ߵ & ) g (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd Ƕ ʶ  % ( * m ~  " $ j m ϸ Ҹ Ը   P r u w (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd* ~ w ̹ *  ݼ ׽   Q 2 x : d  $ i  Z 6 q Q j @ V   ? X f |  & \ M  / J K J 0 T n  ! 6 j n hOdB*CJ^JaJph!h2khOdB* CJ^JaJphXw ̹ ι J p s u # & ( * m  # & ( p s ּ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdּ ټ ۼ ݼ $ ' \ _ a ҽ ս ׽  1 4 g j l  5 8 (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd8 ؿ ۿ  G I m q 1 K N Q 1 x (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   2 4 8 : d  " $ i     Z (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd $ 1 5 q 9 G L P j = ? V     (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd L u   r u 1 5 X  O Z \ | (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd|   & S  P [ _ b y | ~ ' I \  J (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdJ ~ G K    Q T k n p r  K (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   2 6 G ( , < @ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd / 1 E G # ' . 2 c g i J   ? C G I (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd 0 E I k  ; F H o 9 n p (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd 3 6 m  , D F l n     6  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd 5 j l n  3 6 ? s  2 8 g m  ) , (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdn  - A "  Z P e   M    L x  0 ~ / = t ! 5 z C x  0 T V |    X Z       ] R  hOdB*CJ^JaJph!h2khOdB* CJ^JaJphX, A x F  4 _ o " R  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  Z T W e h ' ) e i (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   D I   M ' + h u (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd j m  3 j n  : T e  L w D H (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdH   @ F ' + . 0  > y | ~ / (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  d f @ B o s  B  ( @ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  = e   Y = p s ! (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd 0 3 5 p   K u x z  % C       + - G K   (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd T |        P S       " X Z       E }  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd     C     6 ] M P R # a E H (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd > \ H K      k        ^ a c   C  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd  c C    %   {        & A ( b  & o  s   @   & B    * `    # # & C' I* * + =+ >+ + + , - - . . 0 h0 j0 0 21 B1 e1 ~1 1 1 43 k3 9 : : : %; ; v< < = > 4> X> A A B B F G H hOdB*CJ^JaJph!h2khOdB* CJ^JaJphX     % \        w z     ; u     F I K  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd   # % A    $ ' b      & l n    : o r     (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd @    " K     " % B      * W Z ] `     ! $ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd$ X Z     : < ! ! &! Z! ^! u! z! ! ! ! ! " ," " " " # # 3# (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd3# w# # # # # $ .$ V$ $ $ $ $ $ $ % M% % % & & & & h& & & C' ' ' ' (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd' ( ( ( j( m( ( ( ( ( ;) >) q) s) ) ) ) * @* D* G* I* * * * + =+ + + + (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd+ + 3, o, , #- &- V- l- }- - - - - <. . . . . / a/ / / / / 0 h0 0 0 0 (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd0 0 1 1 B1 ~1 1 "2 .2 L2 2 2 2 3 3 03 k3 3 3 3 4 u4 4 4 4 4 4 [5 5 5 (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd5 5 5 6 H6 T6 V6 i6 6 6 6 6 7 P7 \7 ^7 z7 7 7 7 7 8 M8 8 8 8 8 79 99 F9 (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdF9 ~9 9 9 9 9 : s: : : ; ; #; %; A; g; ; ; ; ; ; < < D< m< q< t< v< < < (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd< < (= += [= ]= = = = > )> -> 0> 2> 4> X> ? #? S? c? ~? ? ? ? ? @ @ "@ @@ p@ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdp@ r@ @ @ A A sA uA A A A A A A A .B 0B TB XB B B B B B B B sC vC C C (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdC C D D sD D D D D D &E )E YE E E E E F F 1F 6F :F F F F F F G \G _G (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd_G G G G G HH vH H H H H H H I "I RI TI xI |I J DJ mJ qJ tJ vJ J J J K K (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdH H ~I J vJ J DK K ;L bL M M N ?N UO O Q dQ R S T T /U U V V !W QW X .Y Z A[ G\ m\ _ ` b b c c d d e e f f 1i ]i kp }q r r r s s s t t t u v 7v `v v v w @y iy y y F| I| [| | | | | } W} } hOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphOK >K BK K L 0L 4L 7L 9L ;L bL L L L L M M M M M M N N N N ?N N N N N (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdN N N #O LO PO SO UO O O O O O P $P fP uP P P P P Q Q Q Q dQ Q Q Q Q (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdQ R R TR }R R R R R R R S LS S S S ,T \T ^T T T T T &U *U -U /U rU U U (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdU U U 1V 4V dV fV V V V V W W W !W QW W W W W X X ]X X X X X X X X (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdX .Y {Y ~Y Y Y Y Z Z =Z nZ Z Z Z Z Z Z Z A[ }[ [ [ [ [ \ <\ @\ C\ E\ G\ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdG\ m\ \ \ \ \ ] ] ] ] ] ] ] ] ^ ^ A^ m^ q^ ^ ^ ^ ^ ^ _ _ 3_ __ c_ _ (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd_ _ _ _ _ _ C` ` ` ` a Ca Ga a a b b b b .b b b b )c pc c c c c d (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdd d Wd |d d d d d d e 9e =e pe e e e e e f f ]f f f f f g g :g fg jg (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdjg g g g g g Fh Ih yh h h h (i ,i /i 1i ]i i i j Jj Nj j j j j j Kk Nk ~k (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd~k k k k l l "l $l fl il l l l l "m &m )m +m cm fm m m m m n n n n Tn Wn (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdWn n n n n n o o o 3o 6o ~o o o o o p p Mp fp ip kp p p 5q }q q q $r Pr (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOdPr Tr r r r r r r r r r r s s 0s {s s s s t Vt t t t t t t u /u vu (1(1(1(1(1(10%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdOdvu u v v 7v \v ^v `v v v v v v v w 4w {w w x x lx x y ;y >y @y iy y y y 0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gdOdy y y y z z +z 1z az yz z z z z z *{ 0{ { { { F| I| [| ]| }| | | | | W} &a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdW} } } } } ~ 1~ 4~ K~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # & 3 a c        &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd} } } } } ~ ~ o s  | ˁ B # } Ԇ ~ ݈ . t ɉ ˉ  ۑ  2 ̔  K ֕  ӗ E [ ]  7 9 D j + F ȥ t P ӧ   0 2 T Ϩ ڨ ? @ hOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphQ  \ j m q s  Q T  & 5 8 : < > @ B " V X &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdX Z }   > h Ԇ + . K o q އ   & G &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdG K a ݈ ߈ . 0 I M ɉ ^ b x , T l z  ב &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdב ّ  2 ~ Ē  \ ? ̔  K ֕      n ~   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 8 ` b ӗ ՗  [ 7 Q s  ' ; a 7 D i &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdi n ʠ # < U a Ƥ ( . 2 > A C F ] å ƥ 0 R o r &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdr t ֦ ٦ P ~ ѧ  0 T Ϩ Ө ب ڨ A D   5 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd5 9 > ? @ T X Ī Ȫ ܪ l ǫ . x 8 : U l n &1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd@ A ƪ Ȫ 8 n Ԯ ֮ O ٱ k Ų  ? v - { д  g % h S z ʹ Ժ  o 5 n ɼ  B C ɽ ʽ   > U v 2 < & G  4 [ ~  ) [ ^ c f hOdB*CJ^JaJph!h2khOdB* CJ^JaJphhOdB* CJ^JaJphS # % U Ԯ ֮  J s L O [ ٱ i k ò Ų  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd = ? v + - { δ д  c e g ! $ h k   q s &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd O R z ' ` c Ź ȹ ʹ   . ^ Ժ   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  o 1 4 n p ɼ  B ɽ   > Q T v &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd % ' l . 0 < g  $ G  4 6  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd ) / 1 [ y {  $ & [ c @ t  _ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  @   _ b F  {  . C D E k l  k  r B q Z % d    ` b  hOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJph!h2khOdB* CJ^JaJphO_  ( \ b g k n   A D F   q &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  @ D   a t x z   t     . ? &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd? B C D S W M L t ! g  < i k &a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  C j l  W I . 0 f " O @ B &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdB f   D g i k   E ^ # r  8 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd8 ? q s  1 7 @ F f y  8 q &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdq s ; B U X Z $ ' ; ~ D G &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd    ! % d  6 ' * 7 i  G K &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  G o s  E H X J M &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd * 9 > q ; > |  `  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd > C K P t y  D G   \ ` &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  2 ?  W A D O ` a m n s $ i U  > {  G J   c   B    6 7    N p       ^ i L" }" $ $ M% % % % % & F& & & & :' !h2khOdB* CJ^JaJphhOdB*CJ^JaJphW 3 5 ] a 2 f j m p  1 8 ; = ? l &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  T  A < O ` m s u  i &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   J N / Z  G [ ] &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   3 6 8 :  E O a } ( / 2 N Q S &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdS U  P u |      > c f z  \ | &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd      G J     > A j       7 K O ^ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd^ a c        B z }   6       8 ; J j     &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  $ C M R {      $ O z    & ( 3 ^       D F &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdF T    ) T  + V    F q &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 4 _  8 c e v    ! 5 7 J u w    ( < @ W   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   . Y       C n      . Y       J u   &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd    7 b     9 d      ' ) R f m r w       &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   5 8 l p            * W         K ] &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd]     @ C [         & 0 s z       C J g n &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdn      " ; B Y \ ^    B ]   g k ! ! ! ^! `! &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd`! ! ! ! ! " " " " }" " " " " " " " " # # $# M# Q# k# o# q# # # # # &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd# # $ $ G$ N$ X$ v$ }$ $ $ $ $ $ % % 2% J% L% % % & B& E& & & & 6' 9' :' &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd:' ;' Q' U' r' v' ' ' ' ' ' ( '( )( -( _( ( ( ( ( +) /) 1) c) r) ) ) ) ) .*  &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd:' ;' <' t' v' ' ' ' )( -) 1) ) 2* * * + , , , - - - <. . . . +/ / 0 ?1 .2 2 2 2 2 2 2 2 2 3 14 C4 n4 4 55 5 5 5 6 6 ;7 O7 8 09 s9 [: `: : : L; N; ; "< J= = 6> *? ? @ @ B C C cD D E WE |E E E hOdB*CJ^JaJph!h2khOdB* CJ^JaJphhOdB* CJ^JaJphhOdB*^JphO.* 0* 2* d* r* * * * + -+ 0+ , - - . 9. <. . . . . / / "/ %/ '/ )/ +/ J/ {/  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd{/ / / 0 (0 P0 0 0 0 0 0 0 ?1 o1 r1 1 1 2 )2 ,2 .2 @2 D2 r2 u2 2 2 2 2 2  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd2 2 2 2 2 2 2 2 r3 3 3 3 4 4 /4 14 C4 E4 l4 n4 4 4 4 5 15 35 55 j5 5 5 &a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd5 5 5 6 G6 6 6 6 6 97 ;7 O7 7 7 7 8 m8 8 8 09 q9 s9 9 9 9 1: [: ^: `: : &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd: : : : ; ; L; N; ; ; ; < "< '< < < < = H= L= N= = = = = = = 6> s> v> &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdv> > > #? %? (? *? V? t? ? ? ? `@ c@ @ @ @ &A *A mA A A A A A 3B \B B B B &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdB B B B C /C C C C C C C cD D D D D D E 6E 9E VE |E E E E E &F )F BF &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdE CF dF kF F +G AG G G H H J J K =K oK }K L M HO kS nS oS pS S S SU UU gU U 'V X AY tY Y Z Z Z Z [ \ x\ H^ W` ` b b Le e f *f f g h nh i ~i oj j #k k $l 8l l l l m Tm m yn n -o Jo qo o p 4p vp p p hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphOBF dF gF iF kF F F $G 'G AG G G G G H `H bH }H H H H &I )I cI I I I J !J %J &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd%J 'J )J _J bJ J J J K =K }K K K K K K K K 2L L L M M #M 'M M M M M M &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdM iN N N N N N N N N N N O ?O CO FO HO bO O O O O O P TP VP P P P P &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdP P >Q [Q yQ Q Q R R }R R R R /S AS iS mS nS oS ~S S S S S S ,T pT T U &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd U SU UU gU iU U U U U U U 'V *V PV pV V V | l| | | | | | } } d} } } } &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd} } ~ ~ 0~ @~ C~ X~ h~ k~ {~ ~ ~ ~ ~ ~ ~ ~ ~  ; ? \ p       &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&agdOd     u Q c g U W ǂ 8 @ Ȅ ^ ` ߅ 9 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd9 ; r ɇ  L N   s v y ˉ ; > s v Ƌ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   >    y }  ʍ N Q Ď ǎ Ɏ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 1 Ɛ ɐ ֐   G m q 8 @ i m ˒ ؒ ܒ ޒ 8 ; H t œ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdœ ɓ   - U Y g k m o   : > w  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd ) i ͖ і   P ~ ė Ɨ 3 6 b ǘ ˘  . 2 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd2 W Z } ƙ ʙ љ ՙ I N W \ š ǚ ˚ Κ N Q  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd ! < ? @ A W [ V ˞ ( n ՟  W 0 &1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd0 s   0 L N  G ݣ  `  O Q ~ ֥  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 7 G r ǣ ݣ   @ `  b 5 a E   ^ p Ƭ ج . >  X k Ϯ " + y Я ߯ 3 > N \   e n Dz  $ x H Q  W b ǵ  N 3 ] ! !h2khOdB* CJ^JaJphhOdB*CJ^JaJphX  b  5 v x է  7 9 ] ި    5 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd5 7 ѩ  _ a  E g j { } ޫ  6 J p ج &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdج   > j ~ Э  0 D k Ϯ  + P d ߯  > e y &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdy а % 9 \ ߱  < P n Dz  $ O c г  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 3 Q v մ  . B b ǵ   ( + - / R U | ö  &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd , 0 2 ` x |   9 N ø  3 d g &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd ֹ   V Y [ ] պ غ    ! P Ļ  L O } Ƽ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  P } 9 I Q   ] _ i z  V Z  O y    b S 9 : d < y m . < M N O P T hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphOƼ : ؽ  q  C  I M O  ]   9 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd9 ? [ b g z  , 0 }  K P e &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  : Q V X Z ' M m   ? Y [ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  \ M ;  A D l &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 4 6 H K M O 3 6 _  7 e &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd " % S r t w y  Y a f b f x { }    &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd b 9 p . 1 L O Q S  " 6 9 p   : &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd: E M U  : j P S  5 &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd5 8 9 : 3 9 S n t  / d f   8 :  &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd: < q   D F r t  ! $ t w y B |  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd| , f  B |    + / < g :  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd: ? d h k m % < @   . [ ^  &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd 3 7 : < M N O _ c  D z | ~ % R T ~  &1 &1 &1 &1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gdOd ) v y { ! $ k  G J L x {  (1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1&a&1gdOd h  ? _ 8  " 9 A i q  & . < D Z b t ~ j E : ; < o q p@M x     R8hOdB* CJ^JaJph!h2khOdB* CJ^JaJphhOdB*^JphhOdB*CJ^JaJphO  0 6 \ b  N \ K M O $ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd$ d f h  j n L R ? L R W [ ^ &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd   9 D H K    8 ] `  9 i &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd & < Z t y ~   L x |  Y _ v | &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd 8 j % ) 4 8 ; d h  E &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd  F J e 6 9 : ; M Q m q 5 Y <&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1gdOd<PPN(rpr@&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd:G ' D m    0 o    B ~  & N n   K O &1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdO t v x    ADgj#(Y^bd&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd R'EGy~8pr&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd|eOmCdhPbg&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd1|hY sO   E!{!!" ###$$D%y%%,&2&d&n'')?)))))V*^***+++,,, ,g,h,,,,,,, ----..0...hOdB* CJ^JaJphhOdB*^Jph!h2khOdB* CJ^JaJphhOdB*CJ^JaJphO>A0|2:<eg 26|&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd|~"VX *KM&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdMpr  E!I!!!";"m""" ##>###,$D$I$M$$$y%%&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd%,&.&1&d&&&&&&'5'9';'k'm''''''''' ((((((&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd())?)r)w))))))))<*I*^***** ++++++++,,&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd,g,,,,,,,,,, -- -E-----....0....@///.0&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd./00j1(2245<<<<<>>>?@@APA]AAAAA:B:E:j:n::::::;;2;5;7;;;;; < <c<e<y<|<~<&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd~<<<<<<<<<<<<<<=T=}==>>>>>>> ?a?????&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd???@Q@}@@@@A$A(AEAIAOA]AvA}AAAAAAAAB4B8B;BHB&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdHB`BdBBBBBBBBBBBJCvCCCCCDD8DT{T&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOd{TTTTTTUAULUrU}UUU VVFVUVgVvVVWWW&W0W7WTWpWWW&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gdOdWWWWXXX!X"X#X2X6XcXgXyXXNYY"ZhZkZ}ZZZZZZ [A[D[&1&1&1&1&1&1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdD[q[[[@\B\l\\\\\]Y]]]]^Q^^^^^__3___b____ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOd__3___j``bbffghhKhhii jjjkllo&psss&t7t%x1xdxoxxxxyAyyyz_zzz*{`{{|||}}}~~9Rjsn׉MۑUbdĔ&IR}`!h2khOdB* CJ^JaJphhOdB*CJ^JaJphX_____.`Q`e`h`j````aAaUaXaZa\aaaab#bSbbbbbb &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdbbcc/cXc[c]cccccccd d(dMdQdSdtdwdddddd e.ee &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdeeffffff gIg_gbgdgggggggghhKhhhhhhhi &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gdOdifiiiiiii j>jAj~jjjjjjkk[kkkkkkkk/llll &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1%1%1%1%1%1%1%1%1gdOdllmemmmmEnnno/oooooop$p&p7ppppp*q^qqqr%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdrr5rQrrr5ssssss$t&t7tNthttttzuulvvwXwwww#x%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd#x%x1xKxbxdxoxxxxxxy?yAyyyyz]z_zzzz*{^{`{{||%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd|||`|n|||%}1}}}}~~A~s~~~~~~~~~~9RUW%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdy%7NUb%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd6FSӂւ #*7iyȃՃ58:Q%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdQTx+;HzɅم"2?tĆdž%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOddž(N^s<LY~ۈވ>T%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdTViln׉̊zeh+.֍%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd֍ٍHKM Vߏ+257ѐ MۑX%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdXÒƒ"$NQbۓ_bdĔ&FH%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdHRl#}&r %1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdkϘB[^`ę ADe9ߛ%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdiӜ՜*НH Kˡˢդ()l2BY˩VX?k »ɪh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJph hFq5>* h}5>* h:R;5>* hOdhOdh=&hOdaJ!h2khOdB* CJ^JaJphhOdB*CJ^JaJph;nyӜ՜*adɝ̝ΝН\_h۞ߞ*P%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdH  Kx|ˡfˢ-X%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd6nrդ-0@gDuw(l|%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOdGJqBWĩɩ˩47^%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gdOd&@Vk)-TXkǬʬk%1%1%1%1%1%1%1%1%1%%%%1%1%1%1%1%1%1%1%1%1%1%1%1gd:R;gd}gdOdgdOdk   #%VX=ư&)±ű%1%1%1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R; #%VX=fư_Ƴdzȳnp!#7s/ϸ{)PýFξI;@}2~h:R;B* CJ^JaJph!hh,h:R;B* CJ^JaJphh:R;B*CJ^JaJphh:R;B*^JphOűٱݱ"beٲ޲!Ddgk³ųƳdz*lp&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1P#aP#1P#1P#1P#1gd:R;pȴ˴)-ݵߵ#79PkP#1P#1P#1P#1P#1P#1P#1P#1P#1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;Ƕ˶suxʷ/ϸ{ֹe&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;eP^eqt!#gýŽ/246C&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;CFkξ/@GIϿD[_jOf&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;SmWq$/1@=&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;=fqs ,XjOhn&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1gd:R;+dCk5mL&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;+:erv}2?CORTVps&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;*59}ad&^`29Qw&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;~7a&7N_4`y  Ma&Et24ELNWYq6lvx6 jk*TU|}h:R;B* CJ^JaJphh:R;B*^Jphh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJphOaln7_c'NIUZ\&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;-2`Cw 3fFJLa&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;:Ha&9`cegEm&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;mo]h o(/;>@MP&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R; 24EHUX~JNZlPaP1P1P1P1P1P1P1P1P1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1gd:R; OQQS4WCUYk 6&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;6qs6vx68mt<?Y&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;  j~*bT|!Ofi&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;ijkmnoq+-:=t,0&a#a#1###1#1#1#1#1#1#1#1#1#1#1#1#1#1#1!a!1gd}gd:R;jknoq+Atx ce<"u:L+G}r0g :b 08_h:R;B* CJ^JaJph!hh,h:R;B* CJ^JaJph h:R;5>* hFq5>*h:R;B*^Jphh:R;B*CJ^JaJphI0aex<>Uk"Hoqsu$S!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;SUW"PRw3a68:Ly)+!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;+GxIzB}:y{},Y!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;(LuAwBlnpr.!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;.0]segb 8;n!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;nY; r     S     7      !1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;;g  G r       , S }       7 d        > V X      0f B+I}1U3  M!H"l""###'.'S't'((((*h:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJphX V X        ` q     *=n.1U!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;  69ez0X[3Radf!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;f 36EY_ Ew6j!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;Bad~Ci+-`c6:X!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;EH}9<>be *-/1Uqt!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;t c.13/2mt!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R; > A ` z      !M!O!s!v!!!!"9"@"C"E"H"l""""!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;"""""=#H#####$0$h$$$$-%/%%%%%%&&)&-&1&H&!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;H&m&&&'.'F'N'Q'S't''''''''''((((b(l(((()!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;)")F)J)))))*k*o********+:+=+F+I+_+b+++++++!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;***++,._0J11334&455%888999===??? @@@@@A~BBCTCCDgFFFFFFGGGGGGEHFHGHHHH@JAJBJJILsL-YCY!mhms.tttt7u9uKuvvvdvfvwvh:R;B* CJ^JaJphh:R;B*^Jphh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJphO+,,],s,,,,,, -I-f-j---..A.z.........//a/!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;a////)0\0c0n00000011!1E1H1J11112H2J2222,3/3!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;/3E3i3333444&4K4N4W4Z4{4~444444555Q5d55555!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;56f666667C7Z7]7_7|7777777788 8#8%8q88889!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;999$9b99999999G::::::::;;; ;B;;;;;;!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;;;;<<W<<<<<<<)=Q======>=>n>>>>??%?6?9?!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;9?;?=????? @<@>@@@@@@@@A4A6AnAAAAAAAA,BtBxB!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;xBBBBBBCTCVClCCCCCCCD&D1D3D?DSDpD{D}DDDDDD!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1gd:R;DDDDDAESEEEEEEE5F9F@FDFFFFFFFFFFFFFF!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1a111111gd:R;FF G GGGG!GTGVGGGGGGGGAHDHEHFHQHUHjHlHHHHHH11&a&1&1&1&1&1&1&1&1&1&1&1#a#1#1#1#1#1#1#1#1gd:R;HHHI I9IIIIJJ[[[\^\\\7]~]]]]]5^^^ _o__`0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;`[````````@aaabbbbb9cccccc>ddd+exeefjf0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;jfmfoffffffCggghehhh>iAi]i_iiiHjjj3kkk%l(l*l0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;*lQlTlzlllllllmmhmlmmmmmmnHnLnlnpnnnnn&o*o0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;*oGoKooooooop"pjpnpqppppp qq"qNqzqqqqqqqq0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;q,r0r?rCrFrZr^rirrrrrrrrrrsss!s.s1s~ssssss0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;s.tWt\tntstttttttttt5u9uKuMuZu]uuuuvvvvv0v0%10%10%10%10%10%10%1@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$10%agd:R;0v4vbvfvwvvvvvvvv7wDw]wwwwwwwKxxxx5y9yAyryxy0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd:R;wvsxx~yyyyyzUzVzgzE{{{{{{{{|||p}}35H/1C}CDE@BTdfzQRSq<ah@~ړhh:R;B* CJ^JaJphh:R;B*^Jph!hh,h:R;B* CJ^JaJphh:R;B*CJ^JaJphOxyzy}y~yyyyyyyyzzz!zQzTzUzVzgzizzzzzzzz{A{0%1a1111111111&a&1&1&1&1&1&1&1&1&1&1&1gd:R;A{D{{{{{{ | |8|:|y|}|||||.}k}n}p}}}}}@~~~_&1&1&1$a$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd:R;_+/15H_log|$1$1$1$1$1$1$1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1a1gd:R;-1CERU:<{σ1111111111111a111111111111gd:R;6=?BCDfЄ҄(*GJbf߅ 111&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;@Dnsw؈܈߈K`>BTŠ&1&1&1&1&1&1&1&1&1&1%a%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1gd:R;Š$X݋+/bfz|،ڌF%1%1%1%1%1%1%1%1%1(a(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd:R;gk1dŏɏIMPQRcgʐqs(1(1(1(1(1(1(1(1(1(1(1(1(1(1&a&1&1&1&1&1&1&1&1&1&1&1gd:R;;adߒ9<~ړ&1`d”P~&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;~krٖ$`חBDi˜"$d͙&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;•vٖݖ$(`dחHi˜Ƙ "(dhԙՙ֙68ءZ[\opqͨӨ8\]Ūƪȫ:;<ȭh:R;B* CJ^JaJphh:R;B*^Jph!hh,h:R;B* CJ^JaJphh:R;B*CJ^JaJphM͙Йәԙՙ'DFkޚSvy{)Ҝ!svx&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;x͝+[_Ԟ  #48Im֟&1&1&1&1&1&1&1&1&1&1&1&1&1&a&1&1&1&1&1&1&1&1&1&1&1&1&1gd:R;?Ay+tסK΢Т.ޣ"BEH&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1@$a@$1@$1gd:R;Ȥˤ;VYZ[ko Iknopئ@$1@$1@$1@$1@$1@$1a11111111111 &a &1 &1 &1 &1gd:R;!HVlpçȧ2aw|ŨͨϨѨӨ &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1(a(1(1(1(1(1(1(1(1gd:R;&1x̩ ,7\Ū1ȫ _¬Ƭ2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd:R;269:;NRprȭ߭SV%p˯̯(1&a&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1&1$$$1gd}gd:R;gd:R;˯̯İ\j=(LиӸDs*+¾E  $=?@XYZ,ӻӻӭyyh z B*CJ^JaJph!hO2$h z B* CJ^JaJphh z h+d5>*h+dCJ^JaJh+dB*CJ^JaJphh:R;B*^Jphh:R;B* CJ^JaJphh:R;B*CJ^JaJph!hh,h:R;B* CJ^JaJph h:R;5>* hFq5>*.Iİưݰ ;=8xj$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd:R;гҳ=r}ϴ\õLPR|׶ $1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd:R; LNty׷ܷ޷6]z˸ϸѸҸ04DG]`mp$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1gd:R;Cmqк"&)*+|Asyʼм ]ƽ$1$1$1$1$1$1$1 &a &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1 &1gd:R;ƽɽ #Z¾վپcͿ EG`bps &1 &1 &1 &1 &1 &1 &1 &1a111111111111111111gd:R; $&=?@YZuy(+,-1111111111v:11111111111agd z gd z gd:R;gd:R;,-  jl}BDU<>S?AV"$5 pqIJ|~LN_ 1hiAB|~TVgh z B*CJ^JaJph!hO2$h z B* CJ^JaJphh z B*^JphT-MQ  '+hl}11111111111a11111111111a1gd z @DUWpr:>SUnp}1111111111%a%1%1%1%1%1%1%1%1%1%1%10%a0%10%1gd z =AVXqs $57PR_b0%10%10%10%10%10%10%10%10%1a11111111111a111gd z  (*7:lopq EHIJcg11111111a111111111111a111gd z 9=z~  JN11111111a11111111111a1111gd z N_az| 13LNP]`1111111a111111111111a1111gd z  "$14dghi =@AB`d1111111a11111111111a11111gd z 9=z~RVgi111111a11111111111a111111gd z i(,=?XZgj111111a11111111111a111111gd z g*,=qr@A}TVg.0A  9T,.mce%&ab{|!hO2$h z B* CJ^JaJphh z B*^Jphh z B*CJ^JaJphT*,.;>mpqr <?@A`d111111a11111111111a111111gd z :>{RVgi11111a11111111111a1111111gd z ,0AC\^kn 681111a11111111111a11111111gd z 8EH~ ";=WZ 9;T111a111111111111p!ap!1p!1p!1p!1p!1p!1p!1p!1gd z TVps'TVoq*.@mop!1p!1p!1p!1 a 1 1 1 1 1 1 1 1 1 1 1 1 a 1 1 1 1 1 1 1gd z o aez!$%&JN 1 1 1 1 1%a%1%1%1%1%1%1%1%1%1%1%1%10%a0%10%10%10%10%10%1gd z ]`ab~9<wz{|0%10%10%10%10%10%1 a 1 1 1 1 1 1 1 1 1 1 1 1 a 1 1 1 1 1gd z 68RU02KMgj 1 1 1 1 1 1 1p!ap!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1p!1 a 1 1 1 1gd z 0G^.0oACUW   STUdf ci7>r+m*c  J c h z B* CJ^JaJphh z B*^Jphh z B*CJ^JaJph!hO2$h z B* CJ^JaJphOGIbd~1^`y{, 1 1 1 1 1 1 1 1a111111111111a111gd z ,0Boq?CT111111111a111111111111a11gd z SWh   Bp&SUnp1111111111 a 1 1 1 1 1 1 1 1 1 1 1 1 1gd z 4Qu24NQ8S a 1 1 1 1 1 1 1 1 1 1 1 1 1 a 1 1 1 1 1 1 1 1 1 1gd z PSTUfj,G_w4Kbz 1 1 1"a"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z z/Jf3Ki @`"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z `bfxx#T3IK\U"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z PR ik  U<57 oqa"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z a79x5t2q.m,k'd"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z W >mpr+MPl)c"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z c        ? F I c     > x { }     7 I L "1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z c }  a    2v\r}R FB}eK   6!#/#[#l##$c$$<%7&&&&3'7'O'K+X+Y+++E,F,,,,--..;0L00011222$3%3o3p3377!hO2$h z B* CJ^JaJphh z B*CJ^JaJphXL        I n r u   +.02Swvx"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z  vHSV~3>@i*-Yr"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z 3j=BMOz  3oz|"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z R "QCP=~"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z  Bh#ny{S^c " $ H      "1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z  6!r!}!!!!!!'"b"m"o"|"""###/#W#Z#l#~####$$9$"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z 9$X$\$$$$$$7%:%<%{%% &7&&&&&&3'6'O''''E(((("1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z ((H))))C*J***C+J+X++E,,,,-q-----.....,//"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z //80:0L0000.11111322222$3o33333)4z4455$5"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z $5(55666 7777s778k8888099999':::6;9;N;;;O<"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1"1gd z 7 7s7788899(:::;N;S<T<<<<h=i===>{>|>>>?????'@@@@@=AAABBXBBB/C1CpCCCJDLDDEEeEgEE"F#F$F_GGGHHHHHII&IIITJUJJJKKKh z B* CJ^JaJphh z B*^Jph!hO2$h z B* CJ^JaJphh z B*CJ^JaJphOO<R<S<T<n<r<<<<<< ==(=+=d=g=h=i======>> >"><>?>a111111111111a11111111111gd z ?>w>z>{>|>>>>>>??2?4?N?Q??????????'@)@B@D@^@1a111111111111a1111111111gd z ^@a@@@@@@@@@A=A?AXAZAtAwAAAAAAABB+BXBZBsBuB11 a 1 1 1 1 1 1 1 1 1 1 1 1 a 1 1 1 1 1 1 1 1 1gd z uBBBBBBBBB-C1CCCpCrCCCCCCCCCD DHDLD^DDDD 1 1 1!a!1!1!1!1!1!1!1!1!1!1!1!1!a!1!1!1!1!1!1!1!1gd z DDDDEEEE"E&EcEgEyEEEEEEEF!F"F#FYFyFFFFG2G!1!1!1!1!a!1!1!1!1!1!1!1!1!1!1!1!1a111111gd z 2G_GaGzG|GGGGGGGGGGHHHH1H3H@HCHjHHHHHHHH11111111`"a`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1`"1(a(1gd z HHII&I(I*IAICIEIRIUIqIIIIIIJ#JEJLJPJSJTJUJpJtJJJ(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1a1111gd z JJKK K!K6K8K:KGKJKKKKL.LMLPLQLRLlLpLLLLLLLLL1111111111111111 a 1 1 1 1 1 1 1 1 1 1gd z KKKQLRLLLLLLNMgMMMN NtNvNNMONOOOOaPbPQQRSSXTT$UUUUnWsWWWXXUXXXXCYDYYYYYZ>ZCZZ[\\+]-]]]^^]^y^^^T____A`}`~``` h}5>* h z h z hO2$h z h z B*^Jphh z B*CJ^JaJph!hO2$h z B* CJ^JaJphLLLLLM-MJMMMgMMMNNN N?NCNrNvNNNNNNNNNNOIO 1 1 1 1 1 1 1 1 1 1 18a818181818181818181818181818181gd z IOLOMONOlOpOOOOOOOOOPP#PCP]P`PaPbPuPyPP;QQQQQ@$a@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1@$1(a(1(1(1(1(1(1(1(1gd z Q(RRRRRSSSS1SXSZShSSSSTTTWTTTTTU!U#UUUyU}U(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1gd z }UUUUUUVFVIVsVVVVV9W>WhWlWpWrWWXUXXXXXXXX(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1agd z XXY Y YY8Y:Y=Y?YBYCYDY[Y_YYYYYYZ ZZCZ{ZZ[[[1111111110%a0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1gd z [[M[~[[[[[[\(\+\P\T\\\\\\\\\\\\)]-]?]]]0%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%10%1!a!1!1!1!1!1!1!1gd z ]]]]]]]^]^^^T_W______A`D`z`}`~`````!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!1!$a$gdqgdq$a$gd}gd z gd z ```eXR[S[T[Z[[[\[][_[`[f[g[j[k[m[n[o[ظôhh80JmHnHuh8ho0JmHnHu h80Jjh80JU hqhqUhqhFq56>*h}56>*```````aa'a8aHaTa]ahaxaaaaaaaaabb#b6bGb$a$gdqGb[blbzbbbbbbbbb cc(c6cGcRcbcucccccccccd$a$gdqdd"d*d5d=dJd_dwddddddddde-e;eHe]eme|eeeeee$a$gdqeeX$X3XCXQX`XuXXXXXXXXY&Y:YQYlYzYYYYYYYY$a$gdqga_remember_equipped ga_remove_comp ga_remove_feat ga_replace_comp ga_reputation ga_reset_level ga_reset_level_by_xp ga_restoration ga_restore_equipped ga_roster_add ga_roster_add_blueprint ga_roster_add_object ga_roster_campaignnpc ga_roster_despawn ga_roster_despawn_all ga_roster_gui_screen ga_roster_party_add ga_roster_party_remove ga_roster_party_remove_all ga_roster_rem ga_roster_remove ga_roster_selectable ga_roster_spawn ga_roster_spawn_rand_loc ga_scripthidden ga_setbumpstate ga_setimmortal ga_setplotflag ga_setrecipes ga_set_animation_condition ga_set_associate_state ga_set_gflag ga_set_weapon_visibility ga_set_wwp_controller ga_sound_object_play ga_sound_object_set_position ga_sound_object_set_volume ga_sound_object_stop ga_start_convo ga_start_mod ga_take_gold ga_take_item ga_talkto ga_time_advance ga_time_set ga_unequip_hands  PAGE 3  PAGE 114 YZZ0ZGZTZmZZZZZZZ[[[%[5[A[R[S[^[_[l[m[n[o[&$a$gdc$a$gdc$a$gdq/000P:pc/ =!"$#x$x%,00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"\#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"L#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"L#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"T#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"\#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"l#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"D#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"< #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!", #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%)0P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"4#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%)0P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"L #x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!", #x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!", #x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%)0P:pc/ =!"l#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"l#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"|#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"|#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"\#x$%)0P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%)0P:pc/ =!" #x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"l#x$%, 00P:pc/ =!"l#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"D#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"d#x$%)0P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%)0P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"4#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"|#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"#x$x%)0P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"l#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"l#x$%, 00P:pc/ =!"|#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$x%)0P:pc/ =!"#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"|#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$x%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"$#x$%, 00P:pc/ =!"|#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"$#x$%)0P:pc/ =!"#x$%, 00P:pc/ =!"#x$%)0P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"L #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"< #x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"< #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"L #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!", #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"< #x$%, 00P:pc/ =!"< #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!", #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"< #x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%, 00P:pc/ =!"\#x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!" #x$%, 00P:pc/ =!"|#x$%, 00P:pc/ =!"#x$x%, 00P:pc/ =!"#x$%, 00P:pc/ =!"#x$%&1h:pc/ =!"#$%}DyK _Toc159540233}DyK _Toc159540233}DyK _Toc159540234}DyK _Toc159540234}DyK _Toc159540235}DyK _Toc159540235}DyK _Toc159540236}DyK _Toc159540236}DyK _Toc159540237}DyK _Toc159540237}DyK _Toc159540238}DyK _Toc159540238}DyK _Toc159540239}DyK _Toc159540239}DyK _Toc159540240}DyK _Toc159540240}DyK _Toc159540241}DyK _Toc159540241}DyK _Toc159540242}DyK _Toc159540242}DyK _Toc159540243}DyK _Toc159540243}DyK _Toc159540244}DyK _Toc159540244}DyK _Toc159540245}DyK _Toc159540245}DyK _Toc159540246}DyK _Toc159540246DyK www.kalifornica.comyK Phttp://www.kalifornica.com/yX;H,]ą'c@@@ NormalCJ_HaJmH sH tH Z@Z Fq Heading 1$<@&5CJ KH OJQJ\^JaJ \@\ Fq Heading 2$<@& 56CJOJQJ\]^JaJDA@D Default Paragraph FontRiR  Table Normal4 l4a (k(No ListN@N }TOC 1$ !ha$5;OJQJ\^J6U@6 Fq Hyperlink >*B*ph88 FqTOC 25CJ\aJ66 FqTOC 3 ^CJaJ66 FqTOC 4 ^CJaJ66 FqTOC 5 ^CJaJ66 FqTOC 6 ^CJaJ66 FqTOC 7 ^CJaJ66 FqTOC 8 ^CJaJ66 FqTOC 9 ^CJaJFV@F LFollowedHyperlink >*B* phdOd fDefault1$7$8$H$-B*CJOJQJ^J_HaJmH phsH tH HH g Balloon TextCJOJQJ^JaJ4@4 YHeader  !4 @4 YFooter  !.)@. c Page Numberr k&|(Y*-=/468:CLT\]_`a,u^vvezV~ȏИ c߮Hzm &Z0!%124`51@9ABBiCDDQMRS@UCX\`cEfhism r}urfص2Ӿ F$>*."cd;<ACDH JL!RSVTYo]3_an#xVyb<Y/~ l e<1"%?<AjFJxest').\ ameinnrv){݃;W? 5;Cr+tuw}&{Ι#̧ѭ͸ldI(k auBv%  7d/$k(G)c,0479=?BdD/EHLNpPRStTCVW!ZZbc{efh5k=nxs& B2 ; qI Ag s  /B S h o    & dG d s 6 / D 0 0L~_ `d :;;<6>hjtmKno tuv9x| GʍPe0 "ַf?^7g6xWqJI0^1q2345678:;<J>G@BCCWDL9MPT]^1^_^^^^_E_s____+`Y````a?amaaaa%bSbbbb c9cgccccdMd{ddde3eaeeeefGfuffff-g[gggghAhohhhh'iUiiii j;jijjjj!kOk}kkkl5lcllllmImwmmmn/n]nnnnoCoqoooo)pWppppq=qkqqqq#rQrrrr s7sesssstKtytttu1u_uuuuvBvpvvvv(wVwwwwxlȐ$Rܑ 8f’Lz֓2`Cq͕)Wޖ :hė N|ؘ4bHvҚ+V<jƜ"P~ڝ6dJxԟ0^DrΡ*X>lȣ$Rܤ 8f¥Lz z z z z z zT] g;<7<;<><?<@<X<\<z<}<<<<-=e===>>3>5>C>F>>>"?'?O?w??????@>@@@@@@@@AA AAARAVAAAAAAAAAAB4BeBBBBBBB C CCCC=CCCCDDnDzD~DDDD*E,E_EEEFFFF1FfFiFjFkFFFFFFFF G*G:GaGGGGGG H?HpHrHHHII/I1I>IAIkInIIIJJ9JDJRJ]JhJoJJJJJJJJKK+K/KAKKKKL@LxLLLLLLL,M.M2MjMMMMNN)NFNcNyNNNNNNN O O+O.O8OaOOOOOOOPlPPP2Q4Q8QlQQQQQRR8RCRRRRRRRRRR!SfSSSSSSSSSTT%T\TTTTT,U2UnUtUyU{UUU7V9VhVsVVVVW&WbWdW}WWWWWWWWWWUXXYWYYYYY ZHZSZZZZZZZ[[d[[[\\!\#\{\\\\\2]n]p]r]]]^^^&^>^p^^^"_W_y_{_____`]`c`````/a7a^aaaabbbGbybbbbb=cUcccccccccdddddde#ebemetewexeyeeeeeeefpfff/ggh}hhhhhhhhhh[iiDjsjjjjjjjjAkkklOlWllllllm#mSmmmmnnCnKnsn|no=oGoyooUpwppppq{qr(r1rrrrrrrrss sssNsRsssssssssssssstt)tOtRttttttttttu6u{uuu'vrvvwZw\w^wwwwwwww xDxGxTxdxxxxxyy y yyyyTyyyyz)z+zizzzzzz{G{r{u{{{{| ||D|y|||}@}E}}}~~~~~~/osw  )KMjǀ02Kfiҁց-1C'Xƒ(*E^w„7;]aą*\߆pćGiɈ'7CHLNfik܉#@C-qwŌь֌ڌ(,oՍۍ[b <g,jtِ9HQxԑ Gݒ'CRYē &zڔ  :?z;A(p  OSŘ>#[ܚ<ћQSlϜޜ$'nFKqsu0ՠ77VZ@nʤ4cեץ&QBPT?MQר'59ȩ-/H`yŪߪ*A[uxܫ|ެ"&S\׭1s~:GIگ7i۰'/368:fiܱ pPȳ<t(RYloqȵLö=?x&\߸Q.r}(,7;>Ȼػ+2R`ü q+_dݾ  [Ϳ MOG\` =uw $&Hqx:<SZ*8S%0dFMy;F~&9u!0;=g1`} AH(^\mq U~ '_*EGceru2[]=pz(jl9`j.I&-\c_} Y`$.acYM.oU\=?A`!l$_2l68n68oJT)lnpce T &[]p`KU7Awy{}L'p+46s{} *_a,.U_.8prtv &V5aiX&(c8?AC}Ex%qsz|hl}6dh4EI-V[7;=JMxz 35|HRBD8Bpr!]4;_i7U18fm 9 ; t     1 w     % f p    G   - 4 w ~    k8DZ\7r D|F{G",hDFHt;=W,bdw35Hz8su#-`bOQSU$nH KSU 7 9 ` j     !!-!7!m!o!!!!!" "E"G"I"K"""""""&#p###$$/$r$z$$$D%n%%%% &N&&&&&&&$'&'N''''(O(~(())!)#)&)')():)>)))))))))*S***+<+A+v+++,,,,-+-T----------0.P.........//>/S/W/////80<0{0000 1I1|111112L2j222@3B3D3\3333333344L44445Q555566[6~6666 77P7R777777L888879999999: :r:::;k;;;;;6<R<<<<<<.=8=p=r===>$>c>e>>>>:?J}JJJJK.KaKcKKKKKK5LlLLLLLMMLMNMPMvMMMM:NDNxNzNNNNNO$OYO[OOOOOOOPPPPbPPP>Q@QQQRRIRRRRRRRS!STSVS}SSSSSS"T$TKTUTTTTTTTU%UbUdUUUUUUUVV\VfVVVVVWdWWWWWXFXXXX?YUYWYYYZ!ZgZnZpZrZZZZ"[)[t[[[\T\\\\\\\\],]A]v]]]]];^]^x^^^^^^_0_3_5_X_____``d`k`r`v````a a a a\aaaa(b,bIbMbbbb*c,c.c;c>cjcccccc,d3dddkddddd1e5e7eielemeneeee)fyf}ffffg+g{g}gggggggg hh|hhhhii%i)iiiiiiiij9jLjjjjjjFkhkkkkkkkl;l>l@lcljlll mmomvm}mmmmmnnnnennnn*o.oKoOoooo,p.p0p=p@pjpppppp,q3qdqkqqqqq1r5r7rjrmrnrorrrr0sssssst2ttttttttttuuuuuuv"v)v-vvvvvvvvwIw^wwwwxxXxzxxxxxxx%yNyQySyvy}yyyz&zzzzzzzz%{({){*{z{{{{?|C|`|d||||A}C}E}R}U}}}}}}}C~J~{~~~~~~HLNH /J؁)0҂ق5<CGك܃݃ރ.\qk  7`ce187:;<ȈMQnr‰OQS`c݊NUSWYߌ RÍǍ9T  18ڏ=DKOߐ6{đ59ƒ'*T}NUÔ!SVWX֕ pt"rtvܗߗ u|"z~ʙΙ$giܚߚ 59[gi͛ϛ+-MX[}œ$/7;>?@RVʝߝIw{ÞǞGX\ԟ @inנJˡGIaȢʢעڢQ£ Vդߤ`ϥѥUWŦϦQ<Ȩ#%wĩpŪ;Wƫȫ3=uw)hj?AԮb O_i7sűU\Ѳ#[ijXZѴ Deӵ9fԶK,kѸӸոCȹʹ!3ce7nһNPRx¼<Fz|&[]پ۾ݾ߾d@BK#Y[')PZ *giakiKDhj-4zCDs mMQ Yu*-i`<' jABFRceruw   "$QScHL)-i:?w2`{}"h's1T^&(o"d \cHA (ZdFH9;d3 0:suwD&-W,PZ)+h6ln 7lnS<_S79V B\!#I KM~,.jt5Z^gi*,S]!+_a8:ak2<Y[:fn]9;vKRTV`gD AVZ: > }     K ~      N l   B D F ^          N    S] RTN9 "tm8T0:rt&eg<> _L\f4pRY X|UWAb 6 c     !H!!!!!)"h""""""@#####$0$c$e$$$$$%7%n%%%%%&&N&P&R&x&&&&<'F'z'|'''''(&([(]((((((())))d)))@*B***++K+++++++,#,Y,[,,,,,,,&-(-O-Y-------.&.c.e.......//]/g/////0e000001G1111@2V2X2223"3h3o3q3s3333#4*4u4445U5555555555#6&646~666666667,7.707=7@7n7p7777777778888C8J8L8S8{888888888 989<99998:C:V:::;E;J;l;n;y;;;;;;;;;;;;;;;< <\<^<k<<<<<<<<=g========m>>>>S?X?|??@@@@U@@@@@FAKAuAABJBNBBBB CCC#C'CyC}CCCCCCDHDvDzDDDEFEWE[EEEF F?FhFmFFFFGIGGGGGH/H1HMHOH\H_HHHHIEIGIII'JZJdJJJJKKTKVKKKKK#LJLTLLLLM3MoMMNNFNMNqN{NNNNIOgOOOCPJPxPPPPQQKQMQQQQQQCRRRRRR7SxSSSSTYTTT?UFUUUUUU$V&V(VzVVVGWWWWWXSXiXkXXXY YFYYYYYZSZZZZ[[U[[[[\\V\\\]1];]w]]]^S^U^W^^^_J_L_f_____`;`q`s```` aBaDaWaaaaaaaGbbbbbbc2c?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0! ?0@0" ?0@0# ?0@0$ ?0@0% ?0@0& ?0@0' ?0@0( ?0@0) ?0@0* ?0@0+ ?0@0, ?0@0- ?0@0. ?0@0/ ?0@00 ?0@01 ?0@02 ?0@03 ?0@04 ?0@05 ?0@06 ?0@07 ?0@08 ?0@09 ?0@0: ?0@0; ?0@0< ?0@0= ?0@0> ?0@0? ?0@0@ ?0@0A ?0@0B ?0@0C ?0@0D ?0@0E ?0@0F ?0@0G ?0@0H ?0@0I ?0@0J ?0@0K ?0@0L ?0@0M ?0@0N ?0@0O ?0@0P ?0@0Q ?0@0R ?0@0S ?0@0T ?0@0U ?0@0V ?0@0W ?0@0X ?0@0Y ?0@0Z ?0@0[ ?0@0\ ?0@0] ?0@0^ ?0@0_ ?0@0` ?0@0a ?0@0b ?0@0c ?0@0d ?0@0e ?0@0f ?0@0g ?0@0h ?0@0i ?0@0j ?0@0k ?0@0l ?0@0m ?0@0n ?0@0o ?0@0p ?0@0q ?0@0r ?0@0s ?0@0t ?0@0u ?0@0v ?0@0w ?0@0x ?0@0y ?0@0z ?0@0{ ?0@0| ?0@0} ?0@0~ ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0! ?0@0" ?0@0# ?0@0$ ?0@0% ?0@0& ?0@0' ?0@0( ?0@0) ?0@0* ?0@0+ ?0@0, ?0@0- ?0@0. ?0@0/ ?0@00 ?0@01 ?0@02 ?0@03 ?0@04 ?0@05 ?0@06 ?0@07 ?0@08 ?0@09 ?0@0: ?0@0; ?0@0< ?0@0= ?0@0> ?0@0? ?0@0@ ?0@0A ?0@0B ?0@0C ?0@0D ?0@0E ?0@0F ?0@0G ?0@0H ?0@0I ?0@0J ?0@0K ?0@0L ?0@0M ?0@0N ?0@0O ?0@0P ?0@0Q ?0@0R ?0@0S ?0@0T ?0@0U ?0@0V ?0@0W ?0@0X ?0@0Y ?0@0Z ?0@0[ ?0@0\ ?0@0] ?0@0^ ?0@0_ ?0@0` ?0@0a ?0@0b ?0@0c ?0@0d ?0@0e ?0@0f ?0@0g ?0@0h ?0@0i ?0@0j ?0@0k ?0@0l ?0@0m ?0@0n ?0@0o ?0@0p ?0@0q ?0@0r ?0@0s ?0@0t ?0@0u ?0@0v ?0@0w ?0@0x ?0@0y ?0@0z ?0@0{ ?0@0| ?0@0} ?0@0~ ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0! ?0@0" ?0@0# ?0@0$ ?0@0% ?0@0& ?0@0' ?0@0( ?0@0) ?0@0* ?0@0+ ?0@0, ?0@0- ?0@0. ?0@0/ ?0@00 ?0@01 ?0@02 ?0@03 ?0@04 ?0@05 ?0@06 ?0@07 ?0@08 ?0@09 ?0@0: ?0@0; ?0@0< ?0@0= ?0@0> ?0@0? ?0@0@ ?0@0A ?0@0B ?0@0C ?0@0D ?0@0E ?0@0F ?0@0G ?0@0H ?0@0I ?0@0J ?0@0K ?0@0L ?0@0M ?0@0N ?0@0O ?0@0P ?0@0Q ?0@0R ?0@0S ?0@0T ?0@0U ?0@0V ?0@0W ?0@0X ?0@0Y ?0@0Z ?0@0[ ?0@0\ ?0@0] ?0@0^ ?0@0_ ?0@0` ?0@0a ?0@0b ?0@0c ?0@0d ?0@0e ?0@0f ?0@0g ?0@0h ?0@0i ?0@0j ?0@0k ?0@0l ?0@0m ?0@0n ?0@0o ?0@0p ?0@0q ?0@0r ?0@0s ?0@0t ?0@0u ?0@0v ?0@0w ?0@0x ?0@0y ?0@0z ?0@0{ ?0@0| ?0@0} ?0@0~ ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0! ?0@0" ?0@0# ?0@0$ ?0@0% ?0@0& ?0@0' ?0@0( ?0@0) ?0@0* ?0@0+ ?0@0, ?0@0- ?0@0. ?0@0/ ?0@00 ?0@01 ?0@02 ?0@03 ?0@04 ?0@05 ?0@06 ?0@07 ?0@08 ?0@09 ?0@0: ?0@0; ?0@0< ?0@0= ?0@0> ?0@0? ?0@0@ ?0@0A ?0@0B ?0@0C ?0@0D ?0@0E ?0@0F ?0@0G ?0@0H ?0@0I ?0@0J ?0@0K ?0@0L ?0@0M ?0@0N ?0@0O ?0@0P ?0@0Q ?0@0R ?0@0S ?0@0T ?0@0U ?0@0V ?0@0W ?0@0X ?0@0Y ?0@0Z ?0@0[ ?0@0\ ?0@0] ?0@0^ ?0@0_ ?0@0` ?0@0a ?0@0b ?0@0c ?0@0d ?0@0e ?0@0f ?0@0g ?0@0h ?0@0i ?0@0j ?0@0k ?0@0l ?0@0m ?0@0n ?0@0o ?0@0p ?0@0q ?0@0r ?0@0s ?0@0t ?0@0u ?0@0v ?0@0w ?0@0x ?0@0y ?0@0z ?0@0{ ?0@0| ?0@0} ?0@0~ ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0! ?0@0" ?0@0# ?0@0$ ?0@0% ?0@0& ?0@0' ?0@0( ?0@0) ?0@0* ?0@0+ ?0@0, ?0@0- ?0@0. ?0@0/ ?0@00 ?0@01 ?0@02 ?0@03 ?0@04 ?0@05 ?0@06 ?0@07 ?0@08 ?0@09 ?0@0: ?0@0; ?0@0< ?0@0= ?0@0> ?0@0? ?0@0@ ?0@0A ?0@0B ?0@0C ?0@0D ?0@0E ?0@0F ?0@0G ?0@0H ?0@0I ?0@0J ?0@0K ?0@0L ?0@0M ?0@0N ?0@0O ?0@0P ?0@0Q ?0@0R ?0@0S ?0@0T ?0@0U ?0@0V ?0@0W ?0@0X ?0@0Y ?0@0Z ?0@0[ ?0@0\ ?0@0] ?0@0^ ?0@0_ ?0@0` ?0@0a ?0@0b ?0@0c ?0@0d ?0@0e ?0@0f ?0@0g ?0@0h ?0@0i ?0@0j ?0@0k ?0@0l ?0@0m ?0@0n ?0@0o ?0@0p ?0@0q ?0@0r ?0@0s ?0@0t ?0@0u ?0@0v ?0@0w ?0@0x ?0@0y ?0@0z ?0@0{ ?0@0| ?0@0} ?0@0~ ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0@0s?0@0t?0@0u?0@0v?0@0w?0@0x?0@0y?0@0z?0@0{?0@0|?0@0}?0@0~?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0 ?0@0 ?0@0 ?0@0 ?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0?0@0 ?0@0!?0@0"?0@0#?0@0$?0@0%?0@0&?0@0'?0@0(?0@0)?0@0*?0@0+?0@0,?0@0-?0@0.?0@0/?0@00?0@01?0@02?0@03?0@04?0@05?0@06?0@07?0@08?0@09?0@0:?0@0;?0@0<?0@0=?0@0>?0@0??0@0@?0@0A?0@0B?0@0C?0@0D?0@0E?0@0F?0@0G?0@0H?0@0I?0@0J?0@0K?0@0L?0@0M?0@0N?0@0O?0@0P?0@0Q?0@0R?0@0S?0@0T?0@0U?0@0V?0@0W?0@0X?0@0Y?0@0Z?0@0[?0@0\?0@0]?0@0^?0@0_?0@0`?0@0a?0@0b?0@0c?0@0d?0@0e?0@0f?0@0g?0@0h?0@0i?0@0j?0@0k?0@0l?0@0m?0@0n?0@0o?0@0p?0@0q?0@0r?0H9<:6!#D~q H 1 l $ ^ | ~  & G k "Eh~579w{%BSo5Fd'Hduy|/2468vz;Ll1B^y ?[lps #%')UXpoPRb.1mjl|.GIvy&+J L n q r s !=!@!!!!"Q"y"|"" # ##!#r#t######-$0$$$$$$$$T%x%%%%%%%&&c&g&j&k&l&&&&&&,'q'''''''B(D(x({(|(}((((())))5)7)d)g)))))O*R*U*X*Y*Z*l*p***+^++++++,, ,(,k,m,,,,,,, -G-o-----------.<.@.R.T.t.w.....9////// 0U0000101p11 2Q22222223(3*33334A4C4444444$5^55555555661656<6@6c6g6j66666677'7*7P7x7777777 8:8a8c8|88888888888"9[99999999::::+:/:Z:: ;C;;;;;;N<<<<<==i======>A>C>>>>?????????@@J@o@@@@7A>AAACApAsAAAAABB0B7BzB|BBBCFCMCOCCCCCCCCC2DDDElEE FKFMFQF`FFFFF0GxG{GGGG H H6HAHoHHHHHH IUI\I_IaIcIeIIIII?JAJ]JdJJJKK-KsKKKK5LLpLLLLLLLLLLL(MMMMMMMMM;N>NSNNNNNNO3OROiOtOOOOOOOOOOPhPPPPPQ QDQzQQQQQQQ RRCRRRRRSZSiS{SSSSSST%T,TgTvTTTTTTTTTUU&UCUsUuUUUUUUUVVBVFVNVVVVVVW#W&W(W?W}WWWWX4XQXTXVXXXXXXX3YaYdYYYYYZ7ZZZZZZ$['[b[[[[[\\!\%\2\5\\\\\\\\\\\] ](]H]K]g]j]]]]]]]]]] ^^"^L^P^g^j^^^^____(_,_D_t________%`'`t`````````a aaa4a7a9aeagaaaaaaaaa6bcbb c=ccdd=ddddie~eeeeJf`ffffg)g.g;ggggggMhhhhiii~iiiiijUjXjZj\jjjk"kRk~kkkkkkkk"l{llll+mTm_m}mmmmmPnsnnnnnnnoKoeonoooooop.p7pTpspppppq+q4qoqqqqq rrrMrXr\r_ryr~rrrrsAsFssssst4t}ޠ=?UYp$GSX\dhŢɢ*pt7AHnϤ #'twǥ @*,.DadާCxzΨ٨ #P[_bcd©ũө6{L«īZ]¬ƬȬ -1gkrv psvϮ׮ۮޮ߮V?CSV|ϰAb{Ա1Z]wDzز۲ݲ/2;>UYƳ˳ӳ.48;=x{ʴʹ 7:VhlƵ\~l̷/^aqt DGHI_c̹Ϲ߹jԺTXegڻܻ#Iq|ʼռܼ޼49Iʽ:ZzԾ־FJ\ƿʿCozM\ix/:r} Xgy)8CJT[  V[k4Li ?BDoPR{~[_ln>$479Yl=DvFbik =-bmtvyz{:@YF')F`bdf-4Sqs"grvx )/#)z#Y\vy'+.MPflNlCSUr!#Mho<W^xWpFQUXzJPio2Wx4V\-IKMOjm`d<)WZUY%]apADuhl$R7:zZ~  QUH]s.2 ${2MPm7;=@X\g kv1<HLZ^` ] 557S+x{>BDFu|6=?vxz',ipsu9; 3eilmn?B2 5 E v x         @ D {      0 K f     0 4 A j        2 4 p   Kpw'epQ`r(7BIy7B|#2DS %,W^b+Haz<@Mv#<>{~!R"%&'mr446ru&VYZ[(.  *,SV|~ d        ,!/!0!1!>!B!i!!!W""""" #$#A#C#y#|#~#### $+$/$u$$$$$$$ % %%%%$%(%u%%%&U&Y&f&&&&& ' '!'$'Q'}'''''''((1(8(<(_(c(f(y(|(~(((( )3)l))))))*(*Y*d****+&+H+V+a+++++,,d,,,,,, -M---.I.|... //9/]/h///0!0-00000(1x1111111112222#2&2E2H2e2i222222222222363F3H3_3a3n3q3333333334444145444444444444555:5=5\5_5`5a5z5~55566+606D6R6d6x666666677!717H7_7q77777777 88-8;8O8d8w8888889.9G9`9999999:/:K:c:y::::::;;;1;K;a;t;;;;;;;;<0<D<W<o<<<<<<<<==(=6=Q=j=======>/>K>_>>>>>>??-?H?M?V?[?_?o?q?????????@ @-@0@1@2@L@P@v@z@@@@@@@@@@@AA5A8A9A:AMAQA{AAAAAAAAAAAAB B>BABBBCBYB]BBBBBBBBBBBC C"C&CFCICeChCiCjC}CCCCCCCCD D)D,DIDMDcDgDDDDDDDDDDD&E+E[EEEEEFF$F)F=FKF]FqFFFFFFFF GG*GAGXGjG~GGGGGGGHH&H4HHH\HoHHHHHHI&I?IXI{IIIIII J'JCJ[JqJJJJJJJ KK)KCKYKlKKKKKKKK L(L}d}}}}}!~4~s~~~~82|׀݀i݁04;?*,GJpjnׄڄHJnqrsυх6}І$ACdg!CGtxˆֈڈb ;>Ndhϊъ.Q]bfnrLP`qČߌeg5befgz~bfwy DĐ \^ɑБ $&Yqxƒڒ&:cƓ&H\AfzҕԕWYIyڗ8:}/:s˙\uĚ2g֛ Ibz +24_=~*eg~şȟ*.z~ؠ>B͡ϡݡ(%UY79R7jʥBDTVXZ\y̦ΦЦҦ #Jlw{ԧ&Xڨ 6;Zũ+.MĪ U׫f>{'aخNȯ E}3V|,~0 kn|Ѵմ!>AwzԵ׵صٵ*0HNܶCIԷ۷,.EGx{ոٸ9=DHŹɹݹ"l*P*-123KOc"`zILɾ˾ξҾӾԾFο_ CF&s)-?A^a59MOjlNRehux   #'X[o;[&AF=14cf#[^l-/dg qw0KQ2{U*o@CGY\Q(e%'DG?BEFGcg VYi$5KMim #$%:>w|AE03g#')j)s< NdfjlO:=>?02>u5l!ZI(c35j$ce!ae}&)*+=Auy)-./KGikm}EWhk8^d3Y_:k^bs35il;%(O +Kmoq!"#VZ  "?VX (-DIKosz~*-;x #XZ [_bcdw{ $Dp59LhV)S~u]$ M O i k   % ' ) B l     @ k     6 a     8 c      !Lx!Nv OQS|P"Y)`*,S'aI4e9n Cs =n >rQ6|L9o D w   !B!y!!!"M""""&#(#z###$3$5$b$v$$%G%%%%&&d&&&,'k'''3(y(((9)x)))?***+G+++ ,Z,,,,,1-x-- .P.../a////;00000$1U11112G2x222 3;3l3333-4^44445P55556B6s666747e7777&8W88889I9z999 :>:l::::0;^;;;;"<P<<<<=B=s===>4>e>>>>&?W????@I@z@@@ A;AlAAAA-B^BBBBCPCCCCDBDsDDDE7EeEEEE)FZFFFFGLG}GGG H>HoHHHH0IaIIII"JSJJJJKEKvKKK L7LhLLLL,MZMMMMNON}NNNOAOrOOOPPPFP{PPPQLQNQYQQQQ"RURRRRRS>SoSSSS0TaTTTT"USUUUUVHVyVVV W7WhWWWW&XWXXXY5YfYYYY*ZXZZZZ[J[{[[[ \<\m\\\].]_]]]]#^T^^^^_F_w___`8`i`l`n````/a_aaaabFb|bbbb cIcccc8dsddd'ebeeefQfffg@g{ggg/hjhhh!i_iiijWjjjkOkkkkk l;lolll m@mrmmmn9njnnno7ooooop7pkppp,qcqqqr9rlrrr s;snspsssss-t/tcttuu5uuuuuu.vvvvvJwLwcwwx xx^xxxxylyoyyy!z#z&z)zzzzz{ {${{{{{{{|#|%|O|~||f}h}}}C~~~~2gǀ/1[rt҂O6cQS9ه $Rω:<g]ɌˌH؍>@f214MҐ,OQrtߒ2֓ ]Ȕʔ77lȖ.0oeg˜@ڙ &X֛BDlQž#$^{}̡rt¢hjfhĤkmȥ ortv4OQt9u#өRprūgάЬ$gƭ.0Vͮ,;fޱ;ݲyֳ;=bqs'Զ@Bfη.øuܹCEk[9u"|׾۾ SM=? pr}$&@[]'d gi\^zPRnLNjOQmQSVX7:S!su :{'y{(*J;HJj'h&@BZ(qce~,z(tv(*C>=?BEcfWRThkgi#%=m &r*y{8:V_bd.^GIaF24R;13QFIKNQor]7OQmR []y0w`b|~ 8r"pr!91@?,FHb L@B\`b~ ,{7P^aw6}U8}!5A C ] _ |    ' V     ] _ v     E     F H j    ,l,9;ZM gi!#>~)9;S (mo1`Z\tCBDX$>@Z] fh6e e g   !!.!Z!!!"1"a"""" #h#j###$$+$U$$$$$W%Y%r%%%%X&p&&&&'E'''''F(H(Z((((($)))))*!*|***++-+H+w++++&,,,,,--/-H-u----........?/A/[/]/|// 0 0)0X00001`1b1{11222L22222N3P3j33444T4444 5j5l555!6#6>6|6666)77777@8B8]88889Z9999:k:m:::-;/;Q;;;;<N<<<<=_=a===!>#>E>>>>>????????@a@c@@@AA%ASAAAABlBnBBB%C'CACCCCC+DDDDD:E@Z\z·*,IRʉqsۊ79\  *oˌ͌.FHaL͏ЏfhӐ.0O Mǒ_ace}œ "BYޕ/\^|͗)+HS̙suxz13MOs: Nɝy{DF]aԠik¡ 5M΢ѢgiUWtŤ!#;}إڥ@bdȧ$&FEZ\v &b%߬;=@B`c|9{׮ٮ8MOiUرtvҲ.0P!rδд<PRo= X%{+-Cݺ3pr>@`(*EǽɽM̾')CEGg(*O/1K1rt68\03LUWv  +!bd<?X`N#%FcIKMjO FHbDFb:qsK*,G?fRTnp(s`bz &s"jl*v!hj.{*rt 84|Nps%GIK_1hk|TWj(adt "4jm}RUgj #Acey]`t$\_t  X[nLOi'*:d#&(*<e@CV~EKmp"DF\(WYp02HuwNPj*,Fuxz|W3\X  F.hQ@}.gZ Ay{(bd\^ EG79;ORkr0    Q S     %    ;    Y [  ,H ln-0DG`k,TV*@^`5]'VY[or $&5Hce "3L    !m!o!!,"."0"G""##d###)$$$$T%W%k%n%%&& &"&3&&&&L''' (m(o((,).)B))**d****++++S,U,X,[,],,,--"-G-f------...!.#.%.c....//*/I/T/V/l/////////000<0Y0d0f000000000181C1E1k11111111 2'22242[2w222222223"3$3K3g3r3t333333444=4Z4e4g4444444 5 5%5A5L5O5k5555555556$6&6D6e6p6r66666667 7 737>7A7W7j7u7x7777777778"8-8/8I8g8r8t888888999.99999 :{:::;;;;\;`;c;d;e;;;;;;<<<'<)<F<H<J<e<h<<<<<<<T=X====\>_>m>>>@?D?U?W?t?v??? @-@1@]@x@}@@@@>AxAAAAAAABBBBEBSBBBBBBBBCCDCfCCCCCCCCCC%D'D+DD[D]D_DzD}DDDDDDDE E}EEEEE"F>FPFlFFFFFFFFFoGrGGGG|HHHHHHHHHII.IDIWIhI|IIIIIIIIIJ J J JJ!JDJtJJJJJJJJIKKKdKkKKKKKKLLKLkLvL}LLLLLLLLMiMMMMMMMNNN1NNNNNNNNCONOOOOOOPP&PKPRPoPPPPP7QqQQQQQQ RRRR R!R"RAR}RRRRRRSS#S%S@SCSSSSSSSSSSSbTTTTTUPUTUfUhUUUUV,VfVhVVVVVVVVVVVhWWWW:XjXXXXXXYYPYSYTYiYmYYYYZ6Z8ZVZlZnZZZZZZ[ [Z[[[[[[[\\\\(\+\-\:\=\?\\\\\\'])]k]n]o]p]]]]]]]]]]]]]D^G^^^^^*_,_/_2_3_4_______3`B`D`X`r`t`v`````a aaaaaa-b3bNbTbbbb7ccccccd!d>dRdidkddddddNeef!f@fPfffffffffgvgyggggh%hRhqhshhhhhhhhiiii jj4jjjjjk3kkkkkkkkk&lXlllmmlmmmmnwnnnnnnnnoo o&oyooop$p&p:pTpVpXpppppppppMqwqq&r5rLrNrPrrrssss s$s'stsssssAttt"uluuuuvvvv v"vIvLvWvvvvw'wMwUwww xxxx x"x#x$xvx|xxxxx>yyyy2zBzDz^zzzzzzzzz{@{B{D{Z{]{{{{{||'|+|S|W|Z|\|^|`|m|p||}}X}\}}}}} ~@~D~~~~= A[yրNRUVWāʁ[O_auwyƃ }Ԅڄ17߅*0Aڇ "6MOQsԈ;=?LOɉDHΊҊ@BDȋlތ0;?  [fj  /13ɏ79VcݐHLaۑ%(RVϒ nsٔ $)IN ?KPt%:Md ƙ˙1HNbsy~ \^՛NSǜҜ֜؜4`-v{5cotןuƠ48h +SXkw"'Qޣ7w%L}vݧ.[fjmŨ'3۪ hn#'Ltʭ+2Yeͮ$1n=Bqv D|"Kylٴݴ oߵ.ZdilM{ķƷȷ˸ùչعڹܹ޹,6owV_ݻ Fq',"'479;=WZsvx Y\^wz7rv HJ^O4Sr&35f  .38$_c AXn[syFw  &;Aw $+06J_eMek7:>EKS3;VZae:NVquxyz?E.0XZ\^abc!'x79;468;<=J[]qs9;EK^`!BH  479FIKTZu{`.Jg{oqBDTWYfiQbd-/1p0Ef [a!58:<ILNP>@J 2f|~5;*9;OiUlp7W\`gkJS -3~Mbdfh}6SUXYZ.45&,MS  "')+./0L]_svxMO9;~>@Ixz}~F L            4 H J           8 >              + - / ^ ` b d f h k l m     ? E          W[(,kpW[7{?C_adefXik 68;<= `qs cg UYq}&MQn),-FG^b0"%7t(2bi)-012EI^btv3 d        !V!!!!"""j""""""""""###5#I########g$k$$%%%_%c%%%%%%%%%4&8&J&&'''5((((((((6)W)Y)z)))*1*3*5*B*E***++,,.,X,\,,,, --3-t---&.-.N.}....../L/w/{//0^0e000001y1111122>2F2z2222222#3,3F3O3T3X3Z33333333@4`4c444555g5555555555T6W6666674767O7S77777+868;88889$9)9H9~9999999999:=:@:::);[;;;;<7<;<><?<@<X<\<z<}<<<<-=e===>>3>5>C>F>>>"?'?O?w??????@>@@@@@@@@AA AAARAVAAAAAAAAAAB4BeBBBBBBB C CCCC=CCCCDDnDzD~DDDD*E,E_EEEFFFF1FfFiFjFkFFFFFFFF G*G:GaGGGGGG H?HpHrHHHII/I1I>IAIkInIIIJJ9JDJRJ]JhJoJJJJJJJJKK+K/KAKKKKL@LxLLLLLLL,M.M2MjMMMMNN)NFNcNyNNNNNNN O O+O.O8OaOOOOOOOPlPPP2Q4Q8QlQQQQQRR8RCRRRRRRRRRR!SfSSSSSSSSSTT%T\TTTTT,U2UnUtUyU{UUU7V9VhVsVVVVW&WbWdW}WWWWWWWWWWUXXYWYYYYY ZHZSZZZZZZZ[[d[[[\\!\#\{\\\\\2]n]p]r]]]^^^&^>^p^^^"_W_y_{_____`]`c`````/a7a^aaaabbbGbybbbbb=cUcccccccccdddddde#ebemetewexeyeeeeeeefpfff/ggh}hhhhhhhhhh[iiDjsjjjjjjjjAkkklOlWllllllm#mSmmmmnnCnKnsn|no=oGoyooUpwppppq{qr(r1rrrrrrrrss sssNsRsssssssssssssstt)tOtRttttttttttu6u{uuu'vrvvwZw\w^wwwwwwww xDxGxTxdxxxxxyy y yyyyTyyyyz)z+zizzzzzz{G{r{u{{{{| ||D|y|||}@}E}}}~~~~~~/osw  )KMjǀ02Kfiҁց-1C'Xƒ(*E^w„7;]aą*\߆pćGiɈ'7CHLNfik܉#@C-qwŌь֌ڌ(,oՍۍ[b <g,jtِ9HQxԑ Gݒ'CRYē &zڔ  :?z;A(p  OSŘ>#[ܚ<ћQSlϜޜ$'nFKqsu0ՠ77VZ@nʤ4cեץ&QBPT?MQר'59ȩ-/H`yŪߪ*A[uxܫ|ެ"&S\׭1s~:GIگ7i۰'/368:fiܱ pPȳ<t(RYloqȵLö=?x&\߸Q.r}(,7;>Ȼػ+2R`ü q+_dݾ  [Ϳ MOG\` =uw $&Hqx:<SZ*8S%0dFMy;F~&9u!0;=g1`} AH(^\mq U~ '_*EGceru2[]=pz(jl9`j.I&-\c_} Y`$.acYM.oU\=?A`!l$_2l68n68oJT)lnpce T &[]p`KU7Awy{}L'p+46s{} *_a,.U_.8prtv &V5aiX&(c8?AC}Ex%qsz|hl}6dh4EI-V[7;=JMxz 35|HRBD8Bpr!]4;_i7U18fm 9 ; t     1 w     % f p    G   - 4 w ~    k8DZ\7r D|F{G",hDFHt;=W,bdw35Hz8su#-`bOQSU$nH KSU 7 9 ` j     !!-!7!m!o!!!!!" "E"G"I"K"""""""&#p###$$/$r$z$$$D%n%%%% &N&&&&&&&$'&'N''''(O(~(())!)#)&)')():)>)))))))))*S***+<+A+v+++,,,,-+-T----------0.P.........//>/S/W/////80<0{0000 1I1|111112L2j222@3B3D3\3333333344L44445Q555566[6~6666 77P7R777777L888879999999: :r:::;k;;;;;6<R<<<<<<.=8=p=r===>$>c>e>>>>:?J}JJJJK.KaKcKKKKKK5LlLLLLLMMLMNMPMvMMMM:NDNxNzNNNNNO$OYO[OOOOOOOPPPPbPPP>Q@QQQRRIRRRRRRRS!STSVS}SSSSSS"T$TKTUTTTTTTTU%UbUdUUUUUUUVV\VfVVVVVWdWWWWWXFXXXX?YUYWYYYZ!ZgZnZpZrZZZZ"[)[t[[[\T\\\\\\\\],]A]v]]]]];^]^x^^^^^^_0_3_5_X_____``d`k`r`v````a a a a\aaaa(b,bIbMbbbb*c,c.c;c>cjcccccc,d3dddkddddd1e5e7eielemeneeee)fyf}ffffg+g{g}gggggggg hh|hhhhii%i)iiiiiiiij9jLjjjjjjFkhkkkkkkkl;l>l@lcljlll mmomvm}mmmmmnnnnennnn*o.oKoOoooo,p.p0p=p@pjpppppp,q3qdqkqqqqq1r5r7rjrmrnrorrrr0sssssst2ttttttttttuuuuuuv"v)v-vvvvvvvvwIw^wwwwxxXxzxxxxxxx%yNyQySyvy}yyyz&zzzzzzzz%{({){*{z{{{{?|C|`|d||||A}C}E}R}U}}}}}}}C~J~{~~~~~~HLNH /J؁)0҂ق5<CGك܃݃ރ.\qk  7`ce187:;<ȈMQnr‰OQS`c݊NUSWYߌ RÍǍ9T  18ڏ=DKOߐ6{đ59ƒ'*T}NUÔ!SVWX֕ pt"rtvܗߗ u|"z~ʙΙ$giܚߚ 59[gi͛ϛ+-MX[}œ$/7;>?@RVʝߝIw{ÞǞGX\ԟ @inנJˡGIaȢʢעڢQ£ Vդߤ`ϥѥUWŦϦQ<Ȩ#%wĩpŪ;Wƫȫ3=uw)hj?AԮb O_i7sűU\Ѳ#[ijXZѴ Deӵ9fԶK,kѸӸոCȹʹ!3ce7nһNPRx¼<Fz|&[]پ۾ݾ߾d@BK#Y[')PZ *giakiKDhj-4zCDs mMQ Yu*-i`<' jABFRceruw   "$QScHL)-i:?w2`{}"h's1T^&(o"d \cHA (ZdFH9;d3 0:suwD&-W,PZ)+h6ln 7lnS<_S79V B\!#I KM~,.jt5Z^gi*,S]!+_a8:ak2<Y[:fn]9;vKRTV`gD AVZ: > }     K ~      N l   B D F ^          N    S] RTN9 "tm8T0:rt&eg<> _L\f4pRY X|UWAb 6 c     !H!!!!!)"h""""""@#####$0$c$e$$$$$%7%n%%%%%&&N&P&R&x&&&&<'F'z'|'''''(&([(]((((((())))d)))@*B***++K+++++++,#,Y,[,,,,,,,&-(-O-Y-------.&.c.e.......//]/g/////0e000001G1111@2V2X2223"3h3o3q3s3333#4*4u4445U5555555555#6&646~666666667,7.707=7@7n7p7777777778888C8J8L8S8{888888888 989<99998:C:V:::;E;J;l;n;y;;;;;;;;;;;;;;;< <\<^<k<<<<<<<<=g========m>>>>S?X?|??@@@@U@@@@@FAKAuAABJBNBBBB CCC#C'CyC}CCCCCCDHDvDzDDDEFEWE[EEEF F?FhFmFFFFGIGGGGGH/H1HMHOH\H_HHHHIEIGIII'JZJdJJJJKKTKVKKKKK#LJLTLLLLM3MoMMNNFNMNqN{NNNNIOgOOOCPJPxPPPPQQKQMQQQQQQCRRRRRR7SxSSSSTYTTT?UFUUUUUU$V&V(VzVVVGWWWWWXSXiXkXXXY YFYYYYYZSZZZZ[[U[[[[\\V\\\]1];]w]]]^S^U^W^^^_J_L_f_____`;`q`s```` aBaDaWaaaaaaaGbbbbbbc2c}E}O}V}}}}}}}}}}}W~~~~~~~~~DFZ^x|~ "%&':>ʀ%Eeȁ 58HKux܂߂a΃ "DXZqxɄ݄$8WAUrІ0\p͇0Lxو$+AHRYpwz{|X\kmŊيۊJ^{؋6auŒ֌1Qލ;OpΎ.[ovxȏϏُݐ=VXovԑNbʒ"6WƓ;t$^rܕAU}̖%9^З CzThoqșʙ͙Ιϙoʚ,TÛś=lǜۜ&:X?SsӞ1\pӟ/O|̠Ӡ"#$7;֡8<IKx{}%MXϣ֣أ Qoĥƥ%3JQjƧȧ˧̧ͧ:֨@CEgi~éͩԩ$^~ª֪ڪ gͫѫޫ79NUìn˭ͭЭѭҭDQZbnwȮҮڮ(4:ALXgpy}/[nӰװ:>^bʱα37TXrvֲڲ;?`d˳ϳ37W[۴ߴ#'GKw{ʵε .2TX{ƶʶ /3RV"&-1ɸ̸͸θ7ֹ۹ "/>N]jz~ѺӺwbf~ͼ,=L\m8v{/2Y\ƿԿ @Di*.Srv#Hjn=\`!JN{37[_ -1\`<@jnAEvz"OSw{!%W[ BFhklm:y} 5_s';`H\cept>fh*.}9=?o  $=Z]PSOS:j:Slo57fhCG#/Y[q @] \`cdeu03EHIJ_c5vSWd (*dgi|=KHPTwa@F>km &*b -/ilb_br #%'()z)z!Z]o{,9=?gjklPVJ tz;Tprtv   DH48GY!CikHO%,.H]`abtx!Z\oqtuv>ABCg -d  ')RUruvw  /1hj})CFV7]?b ]13PRV'.g !$%&w}> D ` z      ! X Z        . 2 B T V |             c t w     ! , ? R c u           %0=NdvDGf'+;?#(CZu/1Jac 26=Aq  3678NR9=OQSln2`cde.x<@02|"(_eux^epwJ` ~    "!j!!!""!">"@""""*#0#a###$+$.$/$0$v${$$$$ %S%%%%%1&b&&&&&&&6'l'n''(!(4(;(E(L(`(g(j(k(l((((((((()C)F)G)H)U)Y)))))))**C*F*~**'+*+z++++++/,?,E,L,_,b,c,d,,,,,,--z--4......//=/@/x///// 0$0P0U0k0p0000000001 1%1]1_1m111:2}222222 336393V3X3o333333334444B4G44445n5r55555)6,6>6@6V6Z6o6666666667777-717_77 8 848w8y8}888888889999 99 9W99: :1:3:k:n:p::::: ;%;,;.;{;;;;"<V<<<<"=T===========> >>i>>>?adahaaaaaaabbbbbbbbbccEcIc[c]cqcsccccccccccd,d.d^dbdudwddddddde@eseueweze{e|eeeeeeeee ffff?fcfxffffffffff*g.gAgCgWgYgfgigggggghhchjhhhhhhhhhh iaicizi|iiiiiijjDjzj~jjj-k1k4k5k6kLkPkkkkkll1l4lAlDlwlylllll2m6mtmmm5n9nnnnnnooXo^ozoooo p"p9p;pHpKp~pppppq9q=qqqqqq rWrcrxrrrr>sJsOstswsxssss8t@Ӊ։؉ډKNg݊&,P̋ϋы?Bqٍ܍ލ.TWY/249psʏ̏ ?b<orܑ*,Ȓ˒\“ƓړݓߓQДz}Nsv֖ adfޗZy2DΙD˚Κ36xiMyShkBHOStʟ W 6[s¡ġơADj!#%},gPS [Yŧȧ:A%+qwȩک PRn.1TKw׭/`®*f Dt԰/d'Ͳ!Rȳ7ZyôQݵVo׸ 9)ֺrŻ'zCƽ9rtL~տ jmoEIK#QTu'/s4~$/3>&)+gjzGVrDCU!Bor .2n6:wGK0AEosEY]mpr>v+lAY7E-VQkmtruLNpr8hkmD:=R\^(+l ADFH'CxMh*+-m ,/13uw+  14.2n<wz|~h8)-9^`K*c3i,.FMw!Hd~#?X , c    C _ y      2 Y u     ! = V        ) C i      " > W ~      6 R k       - < V |      4 P i       E a z 1 @ Z  8 T m # I e ~  2 A [  9 U n      $ J f        < z |        N      T      1 8 b       3 O i      ! H d }      + ? A f       6 R l      $ K g       . B D j       9 U o      ' N j      " 1 E G o       > Z t      * P l      " 1 E G p       ? [ u ! +! Q! m! ! ! ! ! " #" 2" F" H" q" " " " " # # @# \# v# # # # # $ ,$ R$ n$ $ $ $ $ % $% 3% G% N% P% % % % % & & & & & D& H& \& ^& f& }& & & & ' ' ' A' ' ' ' ' ( ( ;( V( X( |( ( ( ( ) ) @) |) ~) ) ) ) * * B* Z* ]* _* * * * * + + F+ J+ M+ + + + + , 3, 6, Z, , - O- g- j- l- - - - - - - . Q. . . . . . . . . &/ Q/ / 0 0 S0 i0 q0 v0 ~0 0 0 0 0 0 0 1 1 "1 $1 G1 1 1 1 1 1 2 :2 >2 A2 B2 C2 Z2 ^2 ~2 2 2 2 2 2 3 )3 R3 T3 3 3 4 %4 '4 :4 =4 4 4 4 45 n5 5 5 5 5 ?6 6 6 6 6 7 7 7 !7 V7 Y7 y7 7 7 8 08 38 58 ~8 8 8 8 8 9 J9 _9 b9 d9 9 9 : D: u: : : ; ; ; ; /; H; K; X; \; k; o; v; z; ; ; ; ; ; ; ; < < < < < < < O= = = = = = )> X> > > > > _? a? ? ? ? @ @ >@ |@ @ @ @ @ @ @ @ +A .A `A dA gA A A A A A A B &B JB MB wB zB |B ~B B B C C 4C hC C C C C D CD ]D D D D D E E /E 6E 8E :E aE eE E E E *F \F vF F F F F F G G G 4G JG LG pG G G G G G G H =H H H I @I gI jI mI pI qI rI I I I I I I J 2K K K 3L xL zL L L L L L -M /M =M oM M M N KN MN ON ^N N O hO O O *P dP P P Q [Q Q R ;R cR R R R S 6S _S S S S T T T T T T PU zU U U U V 6V 8V ^V V V V W EW GW W W X X LX X X X Y FY HY zY Y Y Y :Z mZ oZ Z Z Z ([ u[ [ [ [ \ 3\ h\ j\ l\ \ \ \ ] ] @] D] a] e] g] {] ~] ] ] ] ] ^ ^ !^ %^ G^ L^ _^ d^ f^ ^ ^ ^ ^ ^ ^ _ S_ V_ u_ w_ _ _ _ ` ` ` 2` W` ]` d` h` }` ` ` ` ` "a 'a /a 4a [a a a a a a a a a a b Ub [b zb ~b b b b b b b b b b c ;c >c Tc ec gc {c c c c c c d 5d 9d Id Ld Nd hd d d d d d d e \e _e ye e e e e e e f `f f f f g "g 'g +g Dg Gg Ig zg g g g g !h (h Qh h h h h h h h h i 5i 8i ji i i i i j j ?j ej j j j j j j j j j :k =k Jk k k k k Jl Rl l l l l l l l l ?m m m 'n tn ~n n n n n n 'o Jo No o o o o o o o o o ,p /p p p 'q wq q q q q r r ir r r r r s s s s os s s s t 5t Vt ht jt t t t t t u Wu Zu \u u v Iv Lv v v v v v Mw Pw }w w w w w &x )x Nx }x x x x x x x y y 3y 5y Qy Uy my y y y y 5z 8z :z ]z uz xz z z z z z z z { 9{ >{ { { { { { { { | 5| 9| <| >| f| | | | } } o} s} z} ~} } } } } } ,~ /~ \~ s~ w~ ~ ~ ~ ~     C k n     A x { Ԁ # ' D n s ށ ' . 4 = C h n s v - Ƀ  1 5 j l ߄ : @ n ƅ  G { Æ Ɇ Ά ֆ ۆ     T ч Ӈ   / b g Ԉ ׈ ڈ : d ݉ , W Z \ x Ҋ   D H K M O m { Ë Ƌ  6 M P R ˌ  7 V Z ȍ  9 <  g k ӏ ؏  7 = } Ő  8 ؑ ݑ % n   F J v z | $ ' W Ĕ Ɣ B E k o Е ԕ ו ٕ h ݖ  R ŗ ɗ ݗ 0 p s 0 b e ę ƙ > A  š  \ |  ߛ   / 0 [ ՝  [  _ ן l Π  K  / ӣ  ! # ? U k ѥ ' ) X  G I d ʧ 5 z  a L  p r   C  X : ݮ , a c $ y Z ޱ  Y ײ  Q @ ? ޵   2 g Ͷ ϶  I }  # / 9 B F H e x . ^ C κ E j  x ׽  ,  U q 8 s 5 O Q T 9   C h 8 i  . 0 2 O a ~  V g i Q a e w z |  X i k H X \  ) , U  /     P S k  6 8 x R j m o   i   m ' ? B D G  ^ v y {   ` . 1   K  i  6 N R 9 = A X   # ; Z ] _ , K ; > X Z y = n  3 5 Q T V   / ] ` b w z | ~ B 5 r     \  F y < O   < @ j  ? C F H J ' ) N U   A g 6 9 B S |      !    = d 9 ;  A q D p N W Y ? } ' * , $ C s : f D Y [ ) , . 0 & W K ) + 6  t v   B      3      V      e       v y    M    8     ! 3 / 1 E e & T  c f  3 a l  C  1 F V Y [ ]    1 e    0      K M m t    > E [ ^ `    V g    % L w ~         @ B W   F        > A \ p r        ! R   ( < j           & c     & s      ? i          h    " ! 3! 7! p! ! ! ! ! ?" B" y" " " " " " # +# a# s# # # # # $ 9$ <$ >$ $ $ R% U% |% % % % & #& <& ?& A& & & & "' 7' 9' m' ' ' ' ' ' ' L( e( ~( ( ( ) ) D) K) x) ) ) ) ) * `* k* r* * * * * * * * * .+ 1+ B+ Y+ f+ s+ v+ + + + , , , , w, , - +- O- S- b- e- g- - . . V. r. t. . . / / =/ @/ B/ D/ u/ z/ / / / 40 x0 z0 0 0 0 0 0 ,1 @1 r1 y1 {1 1 1 1 1 ,2 /2 e2 y2 2 2 2 2 3 3 S3 ^3 q3 3 3 3 3 3 3 3 3 4 C4 F4 `4 4 4 4 4 4 4 5 $5 ?5 B5 D5 F5 5 5 6 6 86 D6 k6 6 7 !7 7 8 G8 J8 w8 8 9 T9 q9 x9 9 9 9 9 9 9 g: z: : O; ; 7< 9< |< < < < < < < = = V= o= = = = = = = *> T> V> > > > > ? ? G? Y? a? v? ? ? ? @ @ '@ +@ -@ K@ n@ t@ @ @ @ @ @ A A >A IA MA QA zA A A A A TB XB _B cB B C C !C C D D RD D D E ?E E E E E E E E E E E eF F F F F G @G CG ZG aG G G G G H QH nH uH H H H H H SI I I I J /J fJ J J J J J J J &K (K UK K L L L L L L L &M 2M M M M M $N hN jN N O )O 0O `O qO xO zO O P PP lP P P P P P Q Q a a a a a b Ob b b c Uc Yc [c c c c c c 7d ed d d d d d e +e [e ze }e e e f Bf Df f f %g (g *g u Vu Zu u u 6v hv v v v v Cw |w w w w w 4x Jx |x x y Oy Qy y y y 7z uz wz z z z *{ _{ b{ { { { { | | | | | } B} D} h} } } } %~ '~ X~ ~ ~ ~   7 n p       A m o ̀ π  A C Ɂ ˁ  ; = i ؂ ڂ  , . m ؃    b v   P l   _     x { ҈ و 0 5 > C m r ܉ ߉  % S    4 ; i  ŋ    Z ] ߌ > @ \ l s # * - / a d ˎ ߎ $ a ُ ۏ   ] d g i  C l ё - Z ڒ  1 [  U ܔ  5 k ٕ  6 ` Ŗ  2 5 7 V  ) + @ l p ̘ ј ٘ ޘ  " S Y  N Q i m ɚ 8 n s w ~ ӛ  G m s ? | ߝ  a d ؞ 5 8 : o ȟ ̟ ϟ 3 6 W v x J M m ʡ Ρ " ` d # ) ۣ A E a d { פ ڤ , 1 5 8 I L O   H M ` e g Ԧ  ? A m q Ƨ ʧ ͧ ϧ 4 7 m o ި     L ީ   = S  ; > l p  8 > Z  R Z a g l ҭ 6 ֮ ޮ    / Я    7 l o ˰ ϰ   : F K O v z }    0 4 M Q S   E v { } ϳ   , b d % ) , . V ͵    . [ ^ ٶ ܶ ޶ ' R U    L r u Ѹ Ը , K N  = @ B ߺ : Y \   ? B x | / a f j q u   M P R p % v z }  п ӿ ' + }  T V  ? B v x U  9 I L N d g 8 k o r s t  W  l M Z -    x Y O X 7 9 f  K M o / [ ] * , F p r  D F  0 Z b d   < g i k  ^ I 0 2 O } ? E [ a f i $ ( + e h  ! N T x  _ e { Y p V Z n r u ( + l n  ?   = ^ a c 5 8 S U r  1  * 1 S k r x }   / 3 5 t  P  $ P S  : = ? i  & ^ c f h 3  # ' 2 V a ] ` b 7 9 c  > I M P s  7 B F I  #  [ | A D F ` _ b 3 6 q t v " % ' b $ = h k    " ; P e i k  : = W w  L K  . R U z }   " $ J t w 1   B {   8 `     ! [    B L   * o   G   " i    M O m 3 5 \   0 3 A   } `  $     0 I ~      ( , F ] b     ) , . i   & d      y |      z }      Z ]     t    : = ? r    = @ B u    3 k m     C w z |    ) _ b d     G J L d    " % ' Z    ]       3 5 ! ! _! ! ! ! " " " " o" s" " " " 9# {# # # 9$ |$ $ % % % )% l% % % & S& W& Y& ]& & & ' :' ?' B' ' ' ( ( 4( d( ( ( ( ) P) ~) ) ) * C* q* * * * /+ W+ + + + ", Q, , , , , , , , , C- - - ?. . . . / >/ @/ j/ / / / 90 0 1 b1 f1 1 1 1 +2 Z2 2 2 2 2 2 2 3 3 u3 y3 3 3 3 3 3 3 M4 P4 m4 q4 4 4 4 4 Q5 U5 X5 [5 5 5 5 5 =6 A6 H6 L6 6 6 6 6 7 7 97 =7 7 7 7 7 18 58 88 :8 8 8 8 8 8 8 8 9 9 t9 y9 9 9 : : (: 0: 4: 7: 9: ;: =: w: z: : : : : : : ; ,; .; M; Q; {; ; ; ; ; ; ; ; M< < < < 0= B= E= G= = > > `> > > > > ? ? @? n? r? ? ? ? ? ? ? ? ? @ @ @ S@ @ @ @ @ A /A 3A cA hA A A A A A A B B B B +B .B /B 0B IB MB eB iB |B C VC [C pC C C C C C D D \D xD {D }D D D D D D E EE oE E E E F FF lF F F F F F F F ZG qG tG G G G G G H >H TH `H }H H H H H H I I "I @I VI bI I I I I I I J J "J =J SJ _J J J J J J J J J J K K HK QK SK sK wK K K L L L L AL DL _L L L L L L L L M M M BM EM ]M pM M M M M M M 4N cN gN N N N N N N O O O 0O 4O ^O O O O O O P P CP GP fP P P P P P Q Q 9Q =Q _Q Q Q Q Q Q Q Q Q R !R $R R R R #S %S ES IS yS S S S S S S S S S 2T 5T CT T T TU U U U V LV NV RV dV V V CW W W X pX X RY Y /Z Z Z q[ [ [ \ F\ z\ ] M] ] ] c^ ^ ^ <_ k_ _ ` b` ` ` ^a a b Eb b 'c c c d d d e te f Rf f -g g g Fh h h Ri i i 0j j j [k k k l 2l `l l m ^m m m n 5n 7n 9n Rn jn n n n n n n o 5o 7o Io Ko `o o o o o +p Rp up p p p p q 3q Rq wq q q q q r @r Br rr tr r r r r r s s s s t Ht zt t t u A C E p  ! j m  C E  N c h   0 3 5 7  G Y b f   U Y [ M P m j n ( , . Z \  i    U  0 V 4 j u w 3 5 a d f 2 q 1 3 L P g h l n / 1 3  8 K ] _ { , 2 i o t  = u H $ 4 E H J  w  ]   X [ ] * - b * . k o q  H L N  o r - : e i l n / 2 D F / 3 p }  * _  < R D I   S Y ^ V  > A C R U g ) + q   4 8 O T m  a m  J V o  *  j  5 8 p h k 5 O `  : = ?  w z  g  A s w y   `   a B V k ~  a d f "    n & i l n     R     !     Z     0 m   U X   # & ( v   h k     ! ^ a < ? \ : n    E  ' R U W    1 3 O    4 7 r     p s    D G I     V X t      " % ] p r w     O d f    G      # : ? X v     U a     < H a w             T      - x   Z ]     / 2 b      6 8 h      U ! Q! T! V! ! ! 4" " " " # 1# B# V# Y# o# # $ O$ Q$ i$ $ $ &% r% t% % % % -& u& & & & & & ' C' ' ' ' ( e( q( ( ( ( ( 0) |) ) ) ) :* F* S* * * * + ]+ s+ x+ + + , , , ., q, , , , , - !- #- ?- o- - - - - . U. W. p. . . . / C/ / / / / / 80 x0 0 0 0 0 0 1 ,1 R1 1 1 1 1 1 1 2 22 62 92 ;2 `2 2 2 2 2 3 "3 F3 J3 3 3 3 3 3 3 3 4 4 4 5 (5 C5 E5 i5 m5 5 5 5 5 6 56 76 e6 6 6 6 87 :7 c7 g7 j7 l7 7 7 7 7 7 8 8 N8 w8 {8 ~8 8 8 8 89 ;9 k9 9 9 9 9 8: z: : : : : : : ; f; }; ; ; ; ; ; ; ; {< < < < < < != $= T= V= z= ~= > ;> d> h> k> m> o> > > > ? ? =? A? ? @ 2@ 6@ 9@ ;@ b@ @ @ @ @ A A A A A A A A B 'B sB vB B B B B iC C C C C C C C D YD \D D D D D D E E E E TE E E E E E E +F :F wF F F F F F F F )G G G G G G G H BH FH IH KH MH OH H H I _I I I I !J #J GJ KJ }J J J J J J 7K VK uK K K K K )L +L OL SL L L L L L L M ~M M M M M M "N KN ON RN TN VN N N N @O CO {O O O O O P 3P dP P P P P P P Q BQ EQ uQ Q Q Q R R R R R 2R vR yR R R R R ES hS S S S S S S T 2T 6T ZT T T T T T T T $U (U LU uU yU |U ~U U V EV V V V W W ZW W W W W W W UX X X X 5Y |Y Y Y Y Y Y Z AZ DZ FZ lZ Z Z Z Z [ 5[ ^[ b[ e[ g[ [ [ [ "\ K\ N\ P\ \ \ \ \ +] /] `] ] ] ] ] ^ ^ >^ j^ n^ ^ ^ ^ ^ ^ "_ _ _ _ ` ` q` ` ` ` ` a a Ca oa sa a a a a a +b .b ^b b b b b b b b (c +c [c c c c c c c c d d Ld pd td d d d d d d d Ce e e e e e e f +f .f 0f ef f f Bg g g g h h th h h h h h h h h h h h h @i ui wi i i j Rj Tj Vj {j j j j j ;k hk k k k !l #l %l Jl kl nl l l l l l @m mm m m 1n n n o o o .o Ro Uo o o o o o o o o &p >p Yp up p p p p p Fq Vq q r r r "r Br Dr r r r s s s s s s s s t Dt Kt t t t t t t t t t t &u (u Nu Ru Zu u u u u u !v /v 2v 6v 8v qv v v w w hw qw w w w w w w x x x x wx yx x x y y y y Bz Dz Fz ^z `z bz z z f{ | -| | | | } 4} 6} i} m} } } } } } } } ~ ~ &~ G~ O~ ~ ~ ~ ~     # ' = ρ g   1 ? ߆ y ~ ͇ C ӈ ! i  J ̊  W ċ ȋ ԋ ׋ ً ۋ 3 C s ، ی % ' H i n  8 Ƒ ` x & ŕ . 3 F  ]  u Ι &    " `  4 7 9 f  C F j n ˝  О  D c g Ɵ      \ ^ Ҡ 1 X = |  1 3 M O ~  K M { } Ӥ  8 v   F l Ѧ h . 0 q   ; x z @ ߪ ( * , H J - 0 w z ׬ ٬ 6 8 K N Q S   ? { % ( Z ԯ ׯ # S V X װ ۰ ݰ 4 T W ~ 3 5 S W Ų Dz  H س ڳ    ; h l 1 K P  , l n z  Ƿ D a g > @ e ǹ ( f n y º ĺ  9 ǻ $ c e ¼ ȼ ! ' , 0 3 Z ] _ Խ ׽  Y 6 s ۿ  H [ _ a & 9 = ? 9 L P ~      H L ^   9 a , s u  . 0 b  / 1 f ~   V + W  X   + d , . 0 F n # X Z | 7  6 8 f k  + > D O V i l n R 6 8 _ f     P  C j n I s w ) p s M P R . R V  X [ ] _ 4 8 n  X _   L  6 l q u x z  A Y f i % b     9 > E H n r D l r ! % Z ^ " & c + / 2 5 q u   1 W  y  a   L O % 2 8 : x . h o r t   _ j n p  F I K " G N  [ ^  & B H     X  : A I  ( + ? x ! A E U  H g j   / F Z a   # & ( E k n  ? B p Y  / P p    @ T [ h  ? j # N y  D o q }  D o  F q      6 a      $ O z |    ( * ; f       : < g       G r     I t v     3 ^       I t v  : e ' R } ) T   + 2 7 < P S U W 1 5 g             F p        " q s      Y ` y        8 ? X _       , 3 t {        ! # V    " W   , 0       # %         B D l p           0 4 6 Y `         ; B }          q     p         7 ; L         $ V       ( 7 i k      ) 7 i k d! ! ! " /" 2" z" " " " # # # # # # !# @# q# # # # $ F$ $ $ $ $ $ $ 5% e% h% % % % & "& $& 6& :& h& k& }& & & & & & & & & & & & h' ' ' ' ' ( %( '( 9( ;( b( d( ( ( ( ( ') )) +) `) x) ) ) ) * =* {* }* * * /+ 1+ E+ + + + , c, , , &- g- i- - - - '. Q. T. V. . . . . / / B/ D/ / / / 0 0 0 0 0 0 1 >1 B1 D1 1 1 1 1 1 1 ,2 i2 l2 2 2 3 3 3 3 L3 j3 3 3 3 V4 Y4 4 4 4 5 5 c5 5 5 5 5 5 )6 R6 6 6 6 6 6 6 6 %7 7 7 7 7 7 7 Y8 8 8 8 8 8 8 ,9 /9 L9 r9 u9 w9 9 9 : : 8: Z: ]: _: a: : : ; ; 7; ; ; ; ; < V< X< s< v< x< < = = Y= = = = > > > > > U> X> > > > ? 3? s? y? |? ~? ? ? ? ? (@ @ @ A A A A ~A A A A A _B zB ~B B B B B B B B B C 5C 9C C XC C C C C C D JD LD D D D D D 4E QE oE E E E 2F 4F sF F F F %G 7G _G cG dG eG tG xG G G G G "H fH H I II KI ]I _I vI xI I I I I J J FJ fJ J J 2K cK K K K L \L L L L L 7M hM jM M M N N IN bN N N N N O O hO zO O O O O P *P -P XP iP lP nP P Q yQ Q >R R R R R R R S S 7S ;S VS rS vS }S S S S S S S +T -T HT KT MT T T T T T T U U U U 5U MU QU XU \U sU U U U U U U V V V BV iV V V V #W GW kW W W X bX X X X X X Y Y ;Y >Y @Y BY {Y Y Y Y Y Y Z Z Z LZ tZ Z Z Z Z Z Z Z Z [ h[ k[ [ [ [ \ \ \ d\ \ \ \ ] ] ] H] t] ] ] ] ] ] ] ^ ^ F^ M^ `^ c^ e^ ^ ^ ^ ^ _ _ _ O_ _ _ _ _ _ .` 2` M` Q` ` ` ` ` a a a $a +a /a Aa Ea Ha Ja a a a a &b 9b j   # K O ] a c e ߈ 0 4 m x   _ Ê NJ ׊ ۊ ފ   F t ) , X $ ( M P s w Ǎ ˍ ? D M R Ď ݎ D G   } ؐ ې 2 5 6 7 M Q ّ  L |  d ˓ M & i  & B D ֖ ؖ = ӗ  V  E G t ̙ X u x ߚ + l n ˛ - / S x Ԝ ֜ + - ǝ U W  ; ] ` q s ԟ  , @ f Π  4 ` t ơ ڡ & : a Ţ  ! F Z x գ  4 [ o Ƥ  / R | ե 2 F d  E Y Ƨ  ) G l ˨ ߨ $ 8 X      ! # % H K r " & ( V n r ݫ / D |  ج ۬ ݬ ߬  ) Z ] ̭ ޭ L O Q S ˮ ή     F w ݯ  B E s 0 v α  g 9  ? C E S ص  / 5 Q X ] p ۶ " & s w z ۷  A F [ ޸  0 G L N P ƹ   C c º 5 O Q }  R C 1 ƾ ݾ   7 : b ڿ ܿ * , > A C E y ) , U   - [   I h j m o O W \ X \ n q s u   X / f $ ' B E G I  , / f  0 ; C K | 0 ` F I |    + . / 0 ) / I d j % Z \ u . 0 2 g : < h j    j m o 8 r " \ 8 r u w  ! % 2 ] v { 0 5 Z ^ a c  2 6   $ Q T ) - 0 2 C D E U Y v z  : p r t  H J t  l o q   a  = @ B n q  & , R X D  R  A C E  Z \ ^  ` d  B H 5 B H M Q T / : > A v z . S V  / _   2 P j o t x z  B n r  O U l r w y . `   * . 1 Z ^ { ; z }  < @ [  , / 0 1 C G c g x + O 2 w F F D x  h f h 6 z | 0  =  : c & e 8 t DdAEjln7:]`uyOTXZH{;=ot.fhr[E c     9 Z ^   F X ]         4 7 u   & r   (vx 02[]|(,r}  tLNv ACfhx{;?1cy~4":?Cou"$'Zz~+/1ac 5hm2?T ]          !!!;!!!!!!"$"&"{"""6###$$&$$$`%%%&&F&n&&& ' '!'#'8'<'~'''''''''l(o((((((((U)X)f)x)))))))E*]******X+[+i+}++++++++,!,$,I,M,i,,,,,- ---[-^-r--------..4.8.;.`.d......//(/+/-/////00Y0[0o0r0t0v00000000000021J1s1122222223W33333333G4s4444455;5?5E5S5l5s55555555 6*6.616>6V6Z6z6666666666@7l77777 88.82888F8_8f888888888889 9(9,9/9?9B9D9F9a99999::C:E::::;B;F;;;;;;;;</<`<d<<<</=5=>=D=e=k=m===========$>>>>? ?:?=?????@R@e@k@@@@@@@@ A%A(A+A?ABADAFAAAA7BBBBB CC C@CcCCCCCCCDDDDVDuDD EWEZEiEEEEFF8F?FFFFFF#G.GyGGGGGG4HqHHHHHH I7IBIhIsIIIJJypyyyyyyz(z5zjzzzzzzzzzzz {{{D{T{i{{{{{{|2|B|O|t||||||||||4}J}L}_}b}d}}~~~~p[^!$́ρ>AC܂߂LՃ!(+-~DŽC~х Nvy{}DGXyчUXZ <>Hb|~ s݊ h|au|Ōތ8QTV7:[׎/Տ doɐː WZ‘đƑRU^wђՒ Fw>Anr \w{#N|ܗ,dh˘#&6]vؙ :kmܚbruwܛߛ=@gל8Mv*-T6La  #JNa a֡LNܣޣ3   ϥӥإX[vϦԦ:Z]auy֧ڧ bfy{  #uөթ-/Fa{}ikn%yŬq̭ [FT[x{}֯ gj߰]%(*,9<aIJ%6=?}ų߳:QU`ĴE\IcMg%'6ɸ3\giw޹"N`E^dŻջ׻ٻ!Zּؼ 9a˽+cþž߾  Bÿտ!0[hlsw(59EHJLfi +/s WZTV(/GmWbd-UYD ?KPR#(V  9m)\<@BW0~>W/VY[]vy;cez|S^e%146CF(*;>KNt@DPbEG~GI*M9|~KOa,gi,ln  ,.cjz25O`t XJrE\_`acdegvw~ !#03j   "&W[n24Kaz|>egik}IKMzFHm)W,.0Bo!=n?p8s0oqs"O~Bk7m8bdfhx$&Si|[] X.|1dO1whI-wy LN{ Vg 3d$'K|,/[p&NQy)HWZ\),;OU;m  , `      8 W Z t     9 _ z }    ! # V Y   , 0 N y        ;>s /24X[ #%'KgjY$')u %(cj47VpCEil/69;>b3>&^#%y#'>c$<DGIj  Xb<@ae{03<?UX| S i       ?!\!`!!!""7"p"""""""""%#W####$R$Y$d$$$$$$%%%;%>%@%%%% &>&@&&&&"'%';'_'''''''(A(D(M(P(q(t(((((((((G)Z)))))*\*****+9+P+S+U+r+u+++++++++,,,g,z,,,,- --X--------=..........//8////////0 0M00000001G1u11111 232d22222 33,3/3133333333244464v44444 5*5,5d5y5|555555"6j6n6666666J7L7b7w77777788'8)858I8f8q8s888888888879I9999999+:/:6:::x:|:~::::::::::::;;;;;;J;L;;;;;;;;7<:<;<<<G<K<`<b<<<<<<<<<=/======2>5>6>7>O>y>{>>>>?:?s??? @?@i@k@@@ A=AoAAAB;B=BrBBB C>CnCCC D D@DsDDD E^^^)_{__`` `G`J`p```````aa^abaaaaaaa>bBbbbfbbbbbc c=cAcccccccdd`dddgdddddeeeDepeeeeeeee"f&f5f9ftUtbtetttt]uruuuuuuuuu#v'v9v;vHvKvvvvvvvvv ww0w2wqwuwwwwwwww,x3x5x8x9x:x\xxxxxxxy y=y@yXy\y~yyyyyzzyz{{6{:{{{{d|i|m||||||||A}V}}}}4~8~J~v~~~~~~~~N  !%X\pr΀Ѐ݀< ]a'Z׃?CFGHY]~gi1WZՆ׆/2tЇ 'VZFtz|ahϊV͋8:_܌ތZÍƍɍʍˍ:<aԎIloqvȐilnÑ!QUʒؒ*.?c̓  57o!j͕AĖƖ$ԗ8;>vy|ݘ1LOPQae ?adef{Κ>Lbf(WmrÜŜǜɜ 'n"-Rޞ'U(,/01DHfhա ILf£أܣ?Ӥ13.n`Ƨȧ3hswyŨRߩBFHr}ͪBDjoͫҫԫ,SpŬǬȬ۬߬&*:=SVcf9cg}Ʈ !rx7ioưSP˲ϲ Yó;=VXfiƴʴմٴܴ356OPkoõܵ޵!"#CGöƶ!^bsuҷշַ׷6:KMfhux׸۸04IKdfsv۹߹37LNgivyպٺ+-FHUX -0befg¼Ƽ׼ټ;>?@Y]ʽ̽ٽܽ/3pt@DUWprѿտ')BDFSV'*Z]^_}3678VZ /3pt HL]_xz|"35NP]` "$14cfgh2567VZ 04qu HL]_xz"&79RTad,.;>twxy13MP/1JLfi JLeg $6ce~W[p@DSVWXtx/2mpqr,.HK&(AC]`=?XZtw'TVoq"&8eg59Jwy IM^8fIKdf*Gk (*DG .I} FIJK\`"=Um*AXp%@\x)A_z6VX\nnJ)?A{RKFH_aK2+-zegW-/n+j(g$c"aZM4cfh!CFbY w5<?Y4nqs-?B~?dhk!$&(Im lnl>ILt)46_ #Oh)`3 ~     8 C E p      ) e p r      H       G   9} F3t8^doqITY >~,hswXcer%MPbt  /NR-02q-),E;>9@9@N;    !g!!!!#"w"""""#|##.$0$B$$$$$%z%|%%%)&y&{&&&'e'''''(p(())))),**++++i++,a,,,,&-w----...,///D///E0H0I0J0d0h000000111!1Z1]1^1_1x1|111111222252m2p2q2r222222 33(3*3D3G3~3333333334484:4T4W44444444453555N5P5j5m5555555 66!6N6P6i6k666666666#7'797f7h77777777778>8B8T8888888888899Y9]9o9999999::::O:o:::::(;U;W;p;r;;;;;;;;;;;;<<'<)<6<9<`<<<<<<<<<==== =7=9=;=H=K=g======>>;>B>F>I>J>K>f>j>>>>>>??,?.?0?=?@?????$@C@F@G@H@b@f@@@@@@@@@@@@ A#A@ACA]AAABBBB5B9BhBlBBBBBBBBBBC?CBCCCDCbCfCCCCCCCCCCCD9DSDVDWDXDkDoDD1EEEEEF|FFFFFFG G'GNGPG^GGGGHJHMHHHHHIIIKIoIsIIIIII JUJUSU^UnUUUUUUUUUU VV,V=VQVbVpV|VVVVVVVVWWW,W=WHWXWkWWWWWWWWWWXX X+X3X@XUXmXXXXXXXXX Y#Y1Y>YSYcYrYYYYYYYY ZZ(Z6ZEZZZiZ}ZZZZZZZ [[6[Q[_[p[[[[[[[[[\,\9\R\h\}\\\\\\\] ]]&]7]8]C]U]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[000F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F000Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq0Mq00O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O00R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R000h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h00hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0hz0000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 000v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v0v00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060600uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0uT0މ!#D~q H 1 l $ ^ | ~  & G k "Eh~579w{%BSo5Fd'Hduy|/2468vz;Ll1B^y ?[lps #%')UXpoPRb.1mjl|.GIvy&+J L n q r s !=!@!!!!"Q"y"|"" # ##!#r#t######-$0$$$$$$$$T%x%%%%%%%&&c&g&j&k&l&&&&&&,'q'''''''B(D(x({(|(}((((())))5)7)d)g)))))O*R*U*X*Y*Z*l*p***+^++++++,, ,(,k,m,,,,,,, -G-o-----------.<.@.R.T.t.w.....9////// 0U0000101p11 2Q22222223(3*33334A4C4444444$5^55555555661656<6@6c6g6j66666677'7*7P7x7777777 8:8a8c8|88888888888"9[99999999::::+:/:Z:: ;C;;;;;;N<<<<<==i======>A>C>>>>?????????@@J@o@@@@7A>AAACApAsAAAAABB0B7BzB|BBBCFCMCOCCCCCCCCC2DDDElEE FKFMFQF`FFFFF0GxG{GGGG H H6HAHoHHHHHH IUI\I_IaIcIeIIIII?JAJ]JdJJJKK-KsKKKK5LLpLLLLLLLLLLL(MMMMMMMMM;N>NSNNNNNNO3OROiOtOOOOOOOOOOPhPPPPPQ QDQzQQQQQQQ RRCRRRRRSZSiS{SSSSSST%T,TgTvTTTTTTTTTUU&UCUsUuUUUUUUUVVBVFVNVVVVVVW#W&W(W?W}WWWWX4XQXTXVXXXXXXX3YaYdYYYYYZ7ZZZZZZ$['[b[[[[[\\!\%\2\5\\\\\\\\\\\] ](]H]K]g]j]]]]]]]]]] ^^"^L^P^g^j^^^^____(_,_D_t________%`'`t`````````a aaa4a7a9aeagaaaaaaaaa6bcbb c=ccdd=ddddie~eeeeJf`ffffg)g.g;ggggggMhhhhiii~iiiiijUjXjZj\jjjk"kRk~kkkkkkkk"l{llll+mTm_m}mmmmmPnsnnnnnnnoKoeonoooooop.p7pTpspppppq+q4qoqqqqq rrrMrXr\r_ryr~rrrrsAsFssssst4t}ޠ=?UYp$GSX\dhŢɢ*pt7AHnϤ #'twǥ @*,.DadާCxzΨ٨ #P[_bcd©ũө6{L«īZ]¬ƬȬ -1gkrv psvϮ׮ۮޮ߮V?CSV|ϰAb{Ա1Z]wDzز۲ݲ/2;>UYƳ˳ӳ.48;=x{ʴʹ 7:VhlƵ\~l̷/^aqt DGHI_c̹Ϲ߹jԺTXegڻܻ#Iq|ʼռܼ޼49Iʽ:ZzԾ־FJ\ƿʿCozM\ix/:r} Xgy)8CJT[  V[k4Li ?BDoPR{~[_ln>$479Yl=DvFbik =-bmtvyz{:@YF')F`bdf-4Sqs"grvx )/#)z#Y\vy'+.MPflNlCSUr!#Mho<W^xWpFQUXzJPio2Wx4V\-IKMOjm`d<)WZUY%]apADuhl$R7:zZ~  QUH]s.2 ${2MPm7;=@X\g kv1<HLZ^` ] 557S+x{>BDFu|6=?vxz',ipsu9; 3eilmn?B2 5 E v x         @ D {      0 K f     0 4 A j        2 4 p   Kpw'epQ`r(7BIy7B|#2DS %,W^b+Haz<@Mv#<>{~!R"%&'mr446ru&VYZ[(.  *,SV|~ d        ,!/!0!1!>!B!i!!!W""""" #$#A#C#y#|#~#### $+$/$u$$$$$$$ % %%%%$%(%u%%%&U&Y&f&&&&& ' '!'$'Q'}'''''''((1(8(<(_(c(f(y(|(~(((( )3)l))))))*(*Y*d****+&+H+V+a+++++,,d,,,,,, -M---.I.|... //9/]/h///0!0-00000(1x1111111112222#2&2E2H2e2i222222222222363F3H3_3a3n3q3333333334444145444444444444555:5=5\5_5`5a5z5~55566+606D6R6d6x666666677!717H7_7q77777777 88-8;8O8d8w8888889.9G9`9999999:/:K:c:y::::::;;;1;K;a;t;;;;;;;;<0<D<W<o<<<<<<<<==(=6=Q=j=======>/>K>_>>>>>>??-?H?M?V?[?_?o?q?????????@ @-@0@1@2@L@P@v@z@@@@@@@@@@@AA5A8A9A:AMAQA{AAAAAAAAAAAAB B>BABBBCBYB]BBBBBBBBBBBC C"C&CFCICeChCiCjC}CCCCCCCCD D)D,DIDMDcDgDDDDDDDDDDD&E+E[EEEEEFF$F)F=FKF]FqFFFFFFFF GG*GAGXGjG~GGGGGGGHH&H4HHH\HoHHHHHHI&I?IXI{IIIIII J'JCJ[JqJJJJJJJ KK)KCKYKlKKKKKKKK L(L}d}}}}}!~4~s~~~~82|׀݀i݁04;?*,GJpjnׄڄHJnqrsυх6}І$ACdg!CGtxˆֈڈb ;>Ndhϊъ.Q]bfnrLP`qČߌeg5befgz~bfwy DĐ \^ɑБ $&Yqxƒڒ&:cƓ&H\AfzҕԕWYIyڗ8:}/:s˙\uĚ2g֛ Ibz +24_=~*eg~şȟ*.z~ؠ>B͡ϡݡ(%UY79R7jʥBDTVXZ\y̦ΦЦҦ #Jlw{ԧ&Xڨ 6;Zũ+.MĪ U׫f>{'aخNȯ E}3V|,~0 kn|Ѵմ!>AwzԵ׵صٵ*0HNܶCIԷ۷,.EGx{ոٸ9=DHŹɹݹ"l*P*-123KOc"`zILɾ˾ξҾӾԾFο_ CF&s)-?A^a59MOjlNRehux   #'X[o;[&AF=14cf#[^l-/dg qw0KQ2{U*o@CGY\Q(e%'DG?BEFGcg VYi$5KMim #$%:>w|AE03g#')j)s< NdfjlO:=>?02>u5l!ZI(c35j$ce!ae}&)*+=Auy)-./KGikm}EWhk8^d3Y_:k^bs35il;%(O +Kmoq!"#VZ  "?VX (-DIKosz~*-;x #XZ [_bcdw{ $Dp59LhV)S~u]$ M O i k   % ' ) B l     @ k     6 a     8 c      !Lx!Nv OQS|P"Y)`*,S'aI4e9n Cs =n >rQ6|L9o D w   !B!y!!!"M""""&#(#z###$3$5$b$v$$%G%%%%&&d&&&,'k'''3(y(((9)x)))?***+G+++ ,Z,,,,,1-x-- .P.../a////;00000$1U11112G2x222 3;3l3333-4^44445P55556B6s666747e7777&8W88889I9z999 :>:l::::0;^;;;;"<P<<<<=B=s===>4>e>>>>&?W????@I@z@@@ A;AlAAAA-B^BBBBCPCCCCDBDsDDDE7EeEEEE)FZFFFFGLG}GGG H>HoHHHH0IaIIII"JSJJJJKEKvKKK L7LhLLLL,MZMMMMNON}NNNOAOrOOOPPPFP{PPPQLQNQYQQQQ"RURRRRRS>SoSSSS0TaTTTT"USUUUUVHVyVVV W7WhWWWW&XWXXXY5YfYYYY*ZXZZZZ[J[{[[[ \<\m\\\].]_]]]]#^T^^^^_F_w___`8`i`l`n````/a_aaaabFb|bbbb cIcccc8dsddd'ebeeefQfffg@g{ggg/hjhhh!i_iiijWjjjkOkkkkk l;lolll m@mrmmmn9njnnno7ooooop7pkppp,qcqqqr9rlrrr s;snspsssss-t/tcttuu5uuuuuu.vvvvvJwLwcwwx xx^xxxxylyoyyy!z#z&z)zzzzz{ {${{{{{{{|#|%|O|~||f}h}}}C~~~~2gǀ/1[rt҂O6cQS9ه $Rω:<g]ɌˌH؍>@f214MҐ,OQrtߒ2֓ ]Ȕʔ77lȖ.0oeg˜@ڙ &X֛BDlQž#$^{}̡rt¢hjfhĤkmȥ ortv4OQt9u#өRprūgάЬ$gƭ.0Vͮ,;fޱ;ݲyֳ;=bqs'Զ@Bfη.øuܹCEk[9u"|׾۾ SM=? pr}$&@[]'d gi\^zPRnLNjOQmQSVX7:S!su :{'y{(*J;HJj'h&@BZ(qce~,z(tv(*C>=?BEcfWRThkgi#%=m &r*y{8:V_bd.^GIaF24R;13QFIKNQor]7OQmR []y0w`b|~ 8r"pr!91@?,FHb L@B\`b~ ,{7P^aw6}U8}!5A C ] _ |    ' V     ] _ v     E     F H j    ,l,9;ZM gi!#>~)9;S (mo1`Z\tCBDX$>@Z] fh6e e g   !!.!Z!!!"1"a"""" #h#j###$$+$U$$$$$W%Y%r%%%%X&p&&&&'E'''''F(H(Z((((($)))))*!*|***++-+H+w++++&,,,,,--/-H-u----........?/A/[/]/|// 0 0)0X00001`1b1{11222L22222N3P3j33444T4444 5j5l555!6#6>6|6666)77777@8B8]88889Z9999:k:m:::-;/;Q;;;;<N<<<<=_=a===!>#>E>>>>>????????@a@c@@@AA%ASAAAABlBnBBB%C'CACCCCC+DDDDD:E@Z\z·*,IRʉqsۊ79\  *oˌ͌.FHaL͏ЏfhӐ.0O Mǒ_ace}œ "BYޕ/\^|͗)+HS̙suxz13MOs: Nɝy{DF]aԠik¡ 5M΢ѢgiUWtŤ!#;}إڥ@bdȧ$&FEZ\v &b%߬;=@B`c|9{׮ٮ8MOiUرtvҲ.0P!rδд<PRo= X%{+-Cݺ3pr>@`(*EǽɽM̾')CEGg(*O/1K1rt68\03LUWv  +!bd<?X`N#%FcIKMjO FHbDFb:qsK*,G?fRTnp(s`bz &s"jl*v!hj.{*rt 84|Nps%GIK_1hk|TWj(adt "4jm}RUgj #Acey]`t$\_t  X[nLOi'*:d#&(*<e@CV~EKmp"DF\(WYp02HuwNPj*,Fuxz|W3\X  F.hQ@}.gZ Ay{(bd\^ EG79;ORkr0    Q S     %    ;    Y [  ,H ln-0DG`k,TV*@^`5]'VY[or $&5Hce "3L    !m!o!!,"."0"G""##d###)$$$$T%W%k%n%%&& &"&3&&&&L''' (m(o((,).)B))**d****++++S,U,X,[,],,,--"-G-f------...!.#.%.c....//*/I/T/V/l/////////000<0Y0d0f000000000181C1E1k11111111 2'22242[2w222222223"3$3K3g3r3t333333444=4Z4e4g4444444 5 5%5A5L5O5k5555555556$6&6D6e6p6r66666667 7 737>7A7W7j7u7x7777777778"8-8/8I8g8r8t888888999.99999 :{:::;;;;\;`;c;d;e;;;;;;<<<'<)<F<H<J<e<h<<<<<<<T=X====\>_>m>>>@?D?U?W?t?v??? @-@1@]@x@}@@@@>AxAAAAAAABBBBEBSBBBBBBBBCCDCfCCCCCCCCCC%D'D+DD[D]D_DzD}DDDDDDDE E}EEEEE"F>FPFlFFFFFFFFFoGrGGGG|HHHHHHHHHII.IDIWIhI|IIIIIIIIIJ J J JJ!JDJtJJJJJJJJIKKKdKkKKKKKKLLKLkLvL}LLLLLLLLMiMMMMMMMNNN1NNNNNNNNCONOOOOOOPP&PKPRPoPPPPP7QqQQQQQQ RRRR R!R"RAR}RRRRRRSS#S%S@SCSSSSSSSSSSSbTTTTTUPUTUfUhUUUUV,VfVhVVVVVVVVVVVhWWWW:XjXXXXXXYYPYSYTYiYmYYYYZ6Z8ZVZlZnZZZZZZ[ [Z[[[[[[[\\\\(\+\-\:\=\?\\\\\\'])]k]n]o]p]]]]]]]]]]]]]D^G^^^^^*_,_/_2_3_4_______3`B`D`X`r`t`v`````a aaaaaa-b3bNbTbbbb7ccccccd!d>dRdidkddddddNeef!f@fPfffffffffgvgyggggh%hRhqhshhhhhhhhiiii jj4jjjjjk3kkkkkkkkk&lXlllmmlmmmmnwnnnnnnnnoo o&oyooop$p&p:pTpVpXpppppppppMqwqq&r5rLrNrPrrrssss s$s'stsssssAttt"uluuuuvvvv v"vIvLvWvvvvw'wMwUwww xxxx x"x#x$xvx|xxxxx>yyyy2zBzDz^zzzzzzzzz{@{B{D{Z{]{{{{{||'|+|S|W|Z|\|^|`|m|p||}}X}\}}}}} ~@~D~~~~= A[yրNRUVWāʁ[O_auwyƃ }Ԅڄ17߅*0Aڇ "6MOQsԈ;=?LOɉDHΊҊ@BDȋlތ0;?  [fj  /13ɏ79VcݐHLaۑ%(RVϒ nsٔ $)IN ?KPt%:Md ƙ˙1HNbsy~ \^՛NSǜҜ֜؜4`-v{5cotןuƠ48h +SXkw"'Qޣ7w%L}vݧ.[fjmŨ'3۪ hn#'Ltʭ+2Yeͮ$1n=Bqv D|"Kylٴݴ oߵ.ZdilM{ķƷȷ˸ùչعڹܹ޹,6owV_ݻ Fq',"'479;=WZsvx Y\^wz7rv HJ^O4Sr&35f  .38$_c AXn[syFw  &;Aw $+06J_eMek7:>EKS3;VZae:NVquxyz?E.0XZ\^abc!'x79;468;<=J[]qs9;EK^`!BH  479FIKTZu{`.Jg{oqBDTWYfiQbd-/1p0Ef [a!58:<ILNP>@J 2f|~5;*9;OiUlp7W\`gkJS -3~Mbdfh}6SUXYZ.45&,MS  "')+./0L]_svxMO9;~>@Ixz}~F L            4 H J           8 >              + - / ^ ` b d f h k l m     ? E          W[(,kpW[7{?C_adefXik 68;<= `qs cg UYq}&MQn),-FG^b0"%7t(2bi)-012EI^btv3 d        !V!!!!"""j""""""""""###5#I########g$k$$%%%_%c%%%%%%%%%4&8&J&&'''5((((((((6)W)Y)z)))*1*3*5*B*E***++,,.,X,\,,,, --3-t---&.-.N.}....../L/w/{//0^0e000001y1111122>2F2z2222222#3,3F3O3T3X3Z33333333@4`4c444555g5555555555T6W6666674767O7S77777+868;88889$9)9H9~9999999999:=:@:::);[;;;;<7<;<><?<@<X<\<z<}<<<<-=e===>>3>5>C>F>>>"?'?O?w??????@>@@@@@@@@AA AAARAVAAAAAAAAAAB4BeBBBBBBB C CCCC=CCCCDDnDzD~DDDD*E,E_EEEFFFF1FfFiFjFkFFFFFFFF G*G:GaGGGGGG H?HpHrHHHII/I1I>IAIkInIIIJJ9JDJRJ]JhJoJJJJJJJJKK+K/KAKKKKL@LxLLLLLLL,M.M2MjMMMMNN)NFNcNyNNNNNNN O O+O.O8OaOOOOOOOPlPPP2Q4Q8QlQQQQQRR8RCRRRRRRRRRR!SfSSSSSSSSSTT%T\TTTTT,U2UnUtUyU{UUU7V9VhVsVVVVW&WbWdW}WWWWWWWWWWUXXYWYYYYY ZHZSZZZZZZZ[[d[[[\\!\#\{\\\\\2]n]p]r]]]^^^&^>^p^^^"_W_y_{_____`]`c`````/a7a^aaaabbbGbybbbbb=cUcccccccccdddddde#ebemetewexeyeeeeeeefpfff/ggh}hhhhhhhhhh[iiDjsjjjjjjjjAkkklOlWllllllm#mSmmmmnnCnKnsn|no=oGoyooUpwppppq{qr(r1rrrrrrrrss sssNsRsssssssssssssstt)tOtRttttttttttu6u{uuu'vrvvwZw\w^wwwwwwww xDxGxTxdxxxxxyy y yyyyTyyyyz)z+zizzzzzz{G{r{u{{{{| ||D|y|||}@}E}}}~~~~~~/osw  )KMjǀ02Kfiҁց-1C'Xƒ(*E^w„7;]aą*\߆pćGiɈ'7CHLNfik܉#@C-qwŌь֌ڌ(,oՍۍ[b <g,jtِ9HQxԑ Gݒ'CRYē &zڔ  :?z;A(p  OSŘ>#[ܚ<ћQSlϜޜ$'nFKqsu0ՠ77VZ@nʤ4cեץ&QBPT?MQר'59ȩ-/H`yŪߪ*A[uxܫ|ެ"&S\׭1s~:GIگ7i۰'/368:fiܱ pPȳ<t(RYloqȵLö=?x&\߸Q.r}(,7;>Ȼػ+2R`ü q+_dݾ  [Ϳ MOG\` =uw $&Hqx:<SZ*8S%0dFMy;F~&9u!0;=g1`} AH(^\mq U~ '_*EGceru2[]=pz(jl9`j.I&-\c_} Y`$.acYM.oU\=?A`!l$_2l68n68oJT)lnpce T &[]p`KU7Awy{}L'p+46s{} *_a,.U_.8prtv &V5aiX&(c8?AC}Ex%qsz|hl}6dh4EI-V[7;=JMxz 35|HRBD8Bpr!]4;_i7U18fm 9 ; t     1 w     % f p    G   - 4 w ~    k8DZ\7r D|F{G",hDFHt;=W,bdw35Hz8su#-`bOQSU$nH KSU 7 9 ` j     !!-!7!m!o!!!!!" "E"G"I"K"""""""&#p###$$/$r$z$$$D%n%%%% &N&&&&&&&$'&'N''''(O(~(())!)#)&)')():)>)))))))))*S***+<+A+v+++,,,,-+-T----------0.P.........//>/S/W/////80<0{0000 1I1|111112L2j222@3B3D3\3333333344L44445Q555566[6~6666 77P7R777777L888879999999: :r:::;k;;;;;6<R<<<<<<.=8=p=r===>$>c>e>>>>:?J}JJJJK.KaKcKKKKKK5LlLLLLLMMLMNMPMvMMMM:NDNxNzNNNNNO$OYO[OOOOOOOPPPPbPPP>Q@QQQRRIRRRRRRRS!STSVS}SSSSSS"T$TKTUTTTTTTTU%UbUdUUUUUUUVV\VfVVVVVWdWWWWWXFXXXX?YUYWYYYZ!ZgZnZpZrZZZZ"[)[t[[[\T\\\\\\\\],]A]v]]]]];^]^x^^^^^^_0_3_5_X_____``d`k`r`v````a a a a\aaaa(b,bIbMbbbb*c,c.c;c>cjcccccc,d3dddkddddd1e5e7eielemeneeee)fyf}ffffg+g{g}gggggggg hh|hhhhii%i)iiiiiiiij9jLjjjjjjFkhkkkkkkkl;l>l@lcljlll mmomvm}mmmmmnnnnennnn*o.oKoOoooo,p.p0p=p@pjpppppp,q3qdqkqqqqq1r5r7rjrmrnrorrrr0sssssst2ttttttttttuuuuuuv"v)v-vvvvvvvvwIw^wwwwxxXxzxxxxxxx%yNyQySyvy}yyyz&zzzzzzzz%{({){*{z{{{{?|C|`|d||||A}C}E}R}U}}}}}}}C~J~{~~~~~~HLNH /J؁)0҂ق5<CGك܃݃ރ.\qk  7`ce187:;<ȈMQnr‰OQS`c݊NUSWYߌ RÍǍ9T  18ڏ=DKOߐ6{đ59ƒ'*T}NUÔ!SVWX֕ pt"rtvܗߗ u|"z~ʙΙ$giܚߚ 59[gi͛ϛ+-MX[}œ$/7;>?@RVʝߝIw{ÞǞGX\ԟ @inנJˡGIaȢʢעڢQ£ Vդߤ`ϥѥUWŦϦQ<Ȩ#%wĩpŪ;Wƫȫ3=uw)hj?AԮb O_i7sűU\Ѳ#[ijXZѴ Deӵ9fԶK,kѸӸոCȹʹ!3ce7nһNPRx¼<Fz|&[]پ۾ݾ߾d@BK#Y[')PZ *giakiKDhj-4zCDs mMQ Yu*-i`<' jABFRceruw   "$QScHL)-i:?w2`{}"h's1T^&(o"d \cHA (ZdFH9;d3 0:suwD&-W,PZ)+h6ln 7lnS<_S79V B\!#I KM~,.jt5Z^gi*,S]!+_a8:ak2<Y[:fn]9;vKRTV`gD AVZ: > }     K ~      N l   B D F ^          N    S] RTN9 "tm8T0:rt&eg<> _L\f4pRY X|UWAb 6 c     !H!!!!!)"h""""""@#####$0$c$e$$$$$%7%n%%%%%&&N&P&R&x&&&&<'F'z'|'''''(&([(]((((((())))d)))@*B***++K+++++++,#,Y,[,,,,,,,&-(-O-Y-------.&.c.e.......//]/g/////0e000001G1111@2V2X2223"3h3o3q3s3333#4*4u4445U5555555555#6&646~666666667,7.707=7@7n7p7777777778888C8J8L8S8{888888888 989<99998:C:V:::;E;J;l;n;y;;;;;;;;;;;;;;;< <\<^<k<<<<<<<<=g========m>>>>S?X?|??@@@@U@@@@@FAKAuAABJBNBBBB CCC#C'CyC}CCCCCCDHDvDzDDDEFEWE[EEEF F?FhFmFFFFGIGGGGGH/H1HMHOH\H_HHHHIEIGIII'JZJdJJJJKKTKVKKKKK#LJLTLLLLM3MoMMNNFNMNqN{NNNNIOgOOOCPJPxPPPPQQKQMQQQQQQCRRRRRR7SxSSSSTYTTT?UFUUUUUU$V&V(VzVVVGWWWWWXSXiXkXXXY YFYYYYYZSZZZZ[[U[[[[\\V\\\]1];]w]]]^S^U^W^^^_J_L_f_____`;`q`s```` aBaDaWaaaaaaaGbbbbbbc2c}E}O}V}}}}}}}}}}}W~~~~~~~~~DFZ^x|~ "%&':>ʀ%Eeȁ 58HKux܂߂a΃ "DXZqxɄ݄$8WAUrІ0\p͇0Lxو$+AHRYpwz{|X\kmŊيۊJ^{؋6auŒ֌1Qލ;OpΎ.[ovxȏϏُݐ=VXovԑNbʒ"6WƓ;t$^rܕAU}̖%9^З CzThoqșʙ͙Ιϙoʚ,TÛś=lǜۜ&:X?SsӞ1\pӟ/O|̠Ӡ"#$7;֡8<IKx{}%MXϣ֣أ Qoĥƥ%3JQjƧȧ˧̧ͧ:֨@CEgi~éͩԩ$^~ª֪ڪ gͫѫޫ79NUìn˭ͭЭѭҭDQZbnwȮҮڮ(4:ALXgpy}/[nӰװ:>^bʱα37TXrvֲڲ;?`d˳ϳ37W[۴ߴ#'GKw{ʵε .2TX{ƶʶ /3RV"&-1ɸ̸͸θ7ֹ۹ "/>N]jz~ѺӺwbf~ͼ,=L\m8v{/2Y\ƿԿ @Di*.Srv#Hjn=\`!JN{37[_ -1\`<@jnAEvz"OSw{!%W[ BFhklm:y} 5_s';`H\cept>fh*.}9=?o  $=Z]PSOS:j:Slo57fhCG#/Y[q @] \`cdeu03EHIJ_c5vSWd (*dgi|=KHPTwa@F>km &*b -/ilb_br #%'()z)z!Z]o{,9=?gjklPVJ tz;Tprtv   DH48GY!CikHO%,.H]`abtx!Z\oqtuv>ABCg -d  ')RUruvw  /1hj})CFV7]?b ]13PRV'.g !$%&w}> D ` z      ! X Z        . 2 B T V |             c t w     ! , ? R c u           %0=NdvDGf'+;?#(CZu/1Jac 26=Aq  3678NR9=OQSln2`cde.x<@02|"(_eux^epwJ` ~    "!j!!!""!">"@""""*#0#a###$+$.$/$0$v${$$$$ %S%%%%%1&b&&&&&&&6'l'n''(!(4(;(E(L(`(g(j(k(l((((((((()C)F)G)H)U)Y)))))))**C*F*~**'+*+z++++++/,?,E,L,_,b,c,d,,,,,,--z--4......//=/@/x///// 0$0P0U0k0p0000000001 1%1]1_1m111:2}222222 336393V3X3o333333334444B4G44445n5r55555)6,6>6@6V6Z6o6666666667777-717_77 8 848w8y8}888888889999 99 9W99: :1:3:k:n:p::::: ;%;,;.;{;;;;"<V<<<<"=T===========> >>i>>>?adahaaaaaaabbbbbbbbbccEcIc[c]cqcsccccccccccd,d.d^dbdudwddddddde@eseueweze{e|eeeeeeeee ffff?fcfxffffffffff*g.gAgCgWgYgfgigggggghhchjhhhhhhhhhh iaicizi|iiiiiijjDjzj~jjj-k1k4k5k6kLkPkkkkkll1l4lAlDlwlylllll2m6mtmmm5n9nnnnnnooXo^ozoooo p"p9p;pHpKp~pppppq9q=qqqqqq rWrcrxrrrr>sJsOstswsxssss8t@Ӊ։؉ډKNg݊&,P̋ϋы?Bqٍ܍ލ.TWY/249psʏ̏ ?b<orܑ*,Ȓ˒\“ƓړݓߓQДz}Nsv֖ adfޗZy2DΙD˚Κ36xiMyShkBHOStʟ W 6[s¡ġơADj!#%},gPS [Yŧȧ:A%+qwȩک PRn.1TKw׭/`®*f Dt԰/d'Ͳ!Rȳ7ZyôQݵVo׸ 9)ֺrŻ'zCƽ9rtL~տ jmoEIK#QTu'/s4~$/3>&)+gjzGVrDCU!Bor .2n6:wGK0AEosEY]mpr>v+lAY7E-VQkmtruLNpr8hkmD:=R\^(+l ADFH'CxMh*+-m ,/13uw+  14.2n<wz|~h8)-9^`K*c3i,.FMw!Hd~#?X , c    C _ y      2 Y u     ! = V        ) C i      " > W ~      6 R k       - < V |      4 P i       E a z 1 @ Z  8 T m # I e ~  2 A [  9 U n      $ J f        < z |        N      T      1 8 b       3 O i      ! H d }      + ? A f       6 R l      $ K g       . B D j       9 U o      ' N j      " 1 E G o       > Z t      * P l      " 1 E G p       ? [ u ! +! Q! m! ! ! ! ! " #" 2" F" H" q" " " " " # # @# \# v# # # # # $ ,$ R$ n$ $ $ $ $ % $% 3% G% N% P% % % % % & & & & & D& H& \& ^& f& }& & & & ' ' ' A' ' ' ' ' ( ( ;( V( X( |( ( ( ( ) ) @) |) ~) ) ) ) * * B* Z* ]* _* * * * * + + F+ J+ M+ + + + + , 3, 6, Z, , - O- g- j- l- - - - - - - . Q. . . . . . . . . &/ Q/ / 0 0 S0 i0 q0 v0 ~0 0 0 0 0 0 0 1 1 "1 $1 G1 1 1 1 1 1 2 :2 >2 A2 B2 C2 Z2 ^2 ~2 2 2 2 2 2 3 )3 R3 T3 3 3 4 %4 '4 :4 =4 4 4 4 45 n5 5 5 5 5 ?6 6 6 6 6 7 7 7 !7 V7 Y7 y7 7 7 8 08 38 58 ~8 8 8 8 8 9 J9 _9 b9 d9 9 9 : D: u: : : ; ; ; ; /; H; K; X; \; k; o; v; z; ; ; ; ; ; ; ; < < < < < < < O= = = = = = )> X> > > > > _? a? ? ? ? @ @ >@ |@ @ @ @ @ @ @ @ +A .A `A dA gA A A A A A A B &B JB MB wB zB |B ~B B B C C 4C hC C C C C D CD ]D D D D D E E /E 6E 8E :E aE eE E E E *F \F vF F F F F F G G G 4G JG LG pG G G G G G G H =H H H I @I gI jI mI pI qI rI I I I I I I J 2K K K 3L xL zL L L L L L -M /M =M oM M M N KN MN ON ^N N O hO O O *P dP P P Q [Q Q R ;R cR R R R S 6S _S S S S T T T T T T PU zU U U U V 6V 8V ^V V V V W EW GW W W X X LX X X X Y FY HY zY Y Y Y :Z mZ oZ Z Z Z ([ u[ [ [ [ \ 3\ h\ j\ l\ \ \ \ ] ] @] D] a] e] g] {] ~] ] ] ] ] ^ ^ !^ %^ G^ L^ _^ d^ f^ ^ ^ ^ ^ ^ ^ _ S_ V_ u_ w_ _ _ _ ` ` ` 2` W` ]` d` h` }` ` ` ` ` "a 'a /a 4a [a a a a a a a a a a b Ub [b zb ~b b b b b b b b b b c ;c >c Tc ec gc {c c c c c c d 5d 9d Id Ld Nd hd d d d d d d e \e _e ye e e e e e e f `f f f f g "g 'g +g Dg Gg Ig zg g g g g !h (h Qh h h h h h h h h i 5i 8i ji i i i i j j ?j ej j j j j j j j j j :k =k Jk k k k k Jl Rl l l l l l l l l ?m m m 'n tn ~n n n n n n 'o Jo No o o o o o o o o o ,p /p p p 'q wq q q q q r r ir r r r r s s s s os s s s t 5t Vt ht jt t t t t t u Wu Zu \u u v Iv Lv v v v v v Mw Pw }w w w w w &x )x Nx }x x x x x x x y y 3y 5y Qy Uy my y y y y 5z 8z :z ]z uz xz z z z z z z z { 9{ >{ { { { { { { { | 5| 9| <| >| f| | | | } } o} s} z} ~} } } } } } ,~ /~ \~ s~ w~ ~ ~ ~ ~     C k n     A x { Ԁ # ' D n s ށ ' . 4 = C h n s v - Ƀ  1 5 j l ߄ : @ n ƅ  G { Æ Ɇ Ά ֆ ۆ     T ч Ӈ   / b g Ԉ ׈ ڈ : d ݉ , W Z \ x Ҋ   D H K M O m { Ë Ƌ  6 M P R ˌ  7 V Z ȍ  9 <  g k ӏ ؏  7 = } Ő  8 ؑ ݑ % n   F J v z | $ ' W Ĕ Ɣ B E k o Е ԕ ו ٕ h ݖ  R ŗ ɗ ݗ 0 p s 0 b e ę ƙ > A  š  \ |  ߛ   / 0 [ ՝  [  _ ן l Π  K  / ӣ  ! # ? U k ѥ ' ) X  G I d ʧ 5 z  a L  p r   C  X : ݮ , a c $ y Z ޱ  Y ײ  Q @ ? ޵   2 g Ͷ ϶  I }  # / 9 B F H e x . ^ C κ E j  x ׽  ,  U q 8 s 5 O Q T 9   C h 8 i  . 0 2 O a ~  V g i Q a e w z |  X i k H X \  ) , U  /     P S k  6 8 x R j m o   i   m ' ? B D G  ^ v y {   ` . 1   K  i  6 N R 9 = A X   # ; Z ] _ , K ; > X Z y = n  3 5 Q T V   / ] ` b w z | ~ B 5 r     \  F y < O   < @ j  ? C F H J ' ) N U   A g 6 9 B S |      !    = d 9 ;  A q D p N W Y ? } ' * , $ C s : f D Y [ ) , . 0 & W K ) + 6  t v   B      3      V      e       v y    M    8     ! 3 / 1 E e & T  c f  3 a l  C  1 F V Y [ ]    1 e    0      K M m t    > E [ ^ `    V g    % L w ~         @ B W   F        > A \ p r        ! R   ( < j           & c     & s      ? i          h    " ! 3! 7! p! ! ! ! ! ?" B" y" " " " " " # +# a# s# # # # # $ 9$ <$ >$ $ $ R% U% |% % % % & #& <& ?& A& & & & "' 7' 9' m' ' ' ' ' ' ' L( e( ~( ( ( ) ) D) K) x) ) ) ) ) * `* k* r* * * * * * * * * .+ 1+ B+ Y+ f+ s+ v+ + + + , , , , w, , - +- O- S- b- e- g- - . . V. r. t. . . / / =/ @/ B/ D/ u/ z/ / / / 40 x0 z0 0 0 0 0 0 ,1 @1 r1 y1 {1 1 1 1 1 ,2 /2 e2 y2 2 2 2 2 3 3 S3 ^3 q3 3 3 3 3 3 3 3 3 4 C4 F4 `4 4 4 4 4 4 4 5 $5 ?5 B5 D5 F5 5 5 6 6 86 D6 k6 6 7 !7 7 8 G8 J8 w8 8 9 T9 q9 x9 9 9 9 9 9 9 g: z: : O; ; 7< 9< |< < < < < < < = = V= o= = = = = = = *> T> V> > > > > ? ? G? Y? a? v? ? ? ? @ @ '@ +@ -@ K@ n@ t@ @ @ @ @ @ A A >A IA MA QA zA A A A A TB XB _B cB B C C !C C D D RD D D E ?E E E E E E E E E E E eF F F F F G @G CG ZG aG G G G G H QH nH uH H H H H H SI I I I J /J fJ J J J J J J J &K (K UK K L L L L L L L &M 2M M M M M $N hN jN N O )O 0O `O qO xO zO O P PP lP P P P P P Q Q a a a a a b Ob b b c Uc Yc [c c c c c c 7d ed d d d d d e +e [e ze }e e e f Bf Df f f %g (g *g u Vu Zu u u 6v hv v v v v Cw |w w w w w 4x Jx |x x y Oy Qy y y y 7z uz wz z z z *{ _{ b{ { { { { | | | | | } B} D} h} } } } %~ '~ X~ ~ ~ ~   7 n p       A m o ̀ π  A C Ɂ ˁ  ; = i ؂ ڂ  , . m ؃    b v   P l   _     x { ҈ و 0 5 > C m r ܉ ߉  % S    4 ; i  ŋ    Z ] ߌ > @ \ l s # * - / a d ˎ ߎ $ a ُ ۏ   ] d g i  C l ё - Z ڒ  1 [  U ܔ  5 k ٕ  6 ` Ŗ  2 5 7 V  ) + @ l p ̘ ј ٘ ޘ  " S Y  N Q i m ɚ 8 n s w ~ ӛ  G m s ? | ߝ  a d ؞ 5 8 : o ȟ ̟ ϟ 3 6 W v x J M m ʡ Ρ " ` d # ) ۣ A E a d { פ ڤ , 1 5 8 I L O   H M ` e g Ԧ  ? A m q Ƨ ʧ ͧ ϧ 4 7 m o ި     L ީ   = S  ; > l p  8 > Z  R Z a g l ҭ 6 ֮ ޮ    / Я    7 l o ˰ ϰ   : F K O v z }    0 4 M Q S   E v { } ϳ   , b d % ) , . V ͵    . [ ^ ٶ ܶ ޶ ' R U    L r u Ѹ Ը , K N  = @ B ߺ : Y \   ? B x | / a f j q u   M P R p % v z }  п ӿ ' + }  T V  ? B v x U  9 I L N d g 8 k o r s t  W  l M Z -    x Y O X 7 9 f  K M o / [ ] * , F p r  D F  0 Z b d   < g i k  ^ I 0 2 O } ? E [ a f i $ ( + e h  ! N T x  _ e { Y p V Z n r u ( + l n  ?   = ^ a c 5 8 S U r  1  * 1 S k r x }   / 3 5 t  P  $ P S  : = ? i  & ^ c f h 3  # ' 2 V a ] ` b 7 9 c  > I M P s  7 B F I  #  [ | A D F ` _ b 3 6 q t v " % ' b $ = h k    " ; P e i k  : = W w  L K  . R U z }   " $ J t w 1   B {   8 `     ! [    B L   * o   G   " i    M O m 3 5 \   0 3 A   } `  $     0 I ~      ( , F ] b     ) , . i   & d      y |      z }      Z ]     t    : = ? r    = @ B u    3 k m     C w z |    ) _ b d     G J L d    " % ' Z    ]       3 5 ! ! _! ! ! ! " " " " o" s" " " " 9# {# # # 9$ |$ $ % % % )% l% % % & S& W& Y& ]& & & ' :' ?' B' ' ' ( ( 4( d( ( ( ( ) P) ~) ) ) * C* q* * * * /+ W+ + + + ", Q, , , , , , , , , C- - - ?. . . . / >/ @/ j/ / / / 90 0 1 b1 f1 1 1 1 +2 Z2 2 2 2 2 2 2 3 3 u3 y3 3 3 3 3 3 3 M4 P4 m4 q4 4 4 4 4 Q5 U5 X5 [5 5 5 5 5 =6 A6 H6 L6 6 6 6 6 7 7 97 =7 7 7 7 7 18 58 88 :8 8 8 8 8 8 8 8 9 9 t9 y9 9 9 : : (: 0: 4: 7: 9: ;: =: w: z: : : : : : : ; ,; .; M; Q; {; ; ; ; ; ; ; ; M< < < < 0= B= E= G= = > > `> > > > > ? ? @? n? r? ? ? ? ? ? ? ? ? @ @ @ S@ @ @ @ @ A /A 3A cA hA A A A A A A B B B B +B .B /B 0B IB MB eB iB |B C VC [C pC C C C C C D D \D xD {D }D D D D D D E EE oE E E E F FF lF F F F F F F F ZG qG tG G G G G G H >H TH `H }H H H H H H I I "I @I VI bI I I I I I I J J "J =J SJ _J J J J J J J J J J K K HK QK SK sK wK K K L L L L AL DL _L L L L L L L L M M M BM EM ]M pM M M M M M M 4N cN gN N N N N N N O O O 0O 4O ^O O O O O O P P CP GP fP P P P P P Q Q 9Q =Q _Q Q Q Q Q Q Q Q Q R !R $R R R R #S %S ES IS yS S S S S S S S S S 2T 5T CT T T TU U U U V LV NV RV dV V V CW W W X pX X RY Y /Z Z Z q[ [ [ \ F\ z\ ] M] ] ] c^ ^ ^ <_ k_ _ ` b` ` ` ^a a b Eb b 'c c c d d d e te f Rf f -g g g Fh h h Ri i i 0j j j [k k k l 2l `l l m ^m m m n 5n 7n 9n Rn jn n n n n n n o 5o 7o Io Ko `o o o o o +p Rp up p p p p q 3q Rq wq q q q q r @r Br rr tr r r r r r s s s s t Ht zt t t u A C E p  ! j m  C E  N c h   0 3 5 7  G Y b f   U Y [ M P m j n ( , . Z \  i    U  0 V 4 j u w 3 5 a d f 2 q 1 3 L P g h l n / 1 3  8 K ] _ { , 2 i o t  = u H $ 4 E H J  w  ]   X [ ] * - b * . k o q  H L N  o r - : e i l n / 2 D F / 3 p }  * _  < R D I   S Y ^ V  > A C R U g ) + q   4 8 O T m  a m  J V o  *  j  5 8 p h k 5 O `  : = ?  w z  g  A s w y   `   a B V k ~  a d f "    n & i l n     R     !     Z     0 m   U X   # & ( v   h k     ! ^ a < ? \ : n    E  ' R U W    1 3 O    4 7 r     p s    D G I     V X t      " % ] p r w     O d f    G      # : ? X v     U a     < H a w             T      - x   Z ]     / 2 b      6 8 h      U ! Q! T! V! ! ! 4" " " " # 1# B# V# Y# o# # $ O$ Q$ i$ $ $ &% r% t% % % % -& u& & & & & & ' C' ' ' ' ( e( q( ( ( ( ( 0) |) ) ) ) :* F* S* * * * + ]+ s+ x+ + + , , , ., q, , , , , - !- #- ?- o- - - - - . U. W. p. . . . / C/ / / / / / 80 x0 0 0 0 0 0 1 ,1 R1 1 1 1 1 1 1 2 22 62 92 ;2 `2 2 2 2 2 3 "3 F3 J3 3 3 3 3 3 3 3 4 4 4 5 (5 C5 E5 i5 m5 5 5 5 5 6 56 76 e6 6 6 6 87 :7 c7 g7 j7 l7 7 7 7 7 7 8 8 N8 w8 {8 ~8 8 8 8 89 ;9 k9 9 9 9 9 8: z: : : : : : : ; f; }; ; ; ; ; ; ; ; {< < < < < < != $= T= V= z= ~= > ;> d> h> k> m> o> > > > ? ? =? A? ? @ 2@ 6@ 9@ ;@ b@ @ @ @ @ A A A A A A A A B 'B sB vB B B B B iC C C C C C C C D YD \D D D D D D E E E E TE E E E E E E +F :F wF F F F F F F F )G G G G G G G H BH FH IH KH MH OH H H I _I I I I !J #J GJ KJ }J J J J J J 7K VK uK K K K K )L +L OL SL L L L L L L M ~M M M M M M "N KN ON RN TN VN N N N @O CO {O O O O O P 3P dP P P P P P P Q BQ EQ uQ Q Q Q R R R R R 2R vR yR R R R R ES hS S S S S S S T 2T 6T ZT T T T T T T T $U (U LU uU yU |U ~U U V EV V V V W W ZW W W W W W W UX X X X 5Y |Y Y Y Y Y Y Z AZ DZ FZ lZ Z Z Z Z [ 5[ ^[ b[ e[ g[ [ [ [ "\ K\ N\ P\ \ \ \ \ +] /] `] ] ] ] ] ^ ^ >^ j^ n^ ^ ^ ^ ^ ^ "_ _ _ _ ` ` q` ` ` ` ` a a Ca oa sa a a a a a +b .b ^b b b b b b b b (c +c [c c c c c c c c d d Ld pd td d d d d d d d Ce e e e e e e f +f .f 0f ef f f Bg g g g h h th h h h h h h h h h h h h @i ui wi i i j Rj Tj Vj {j j j j j ;k hk k k k !l #l %l Jl kl nl l l l l l @m mm m m 1n n n o o o .o Ro Uo o o o o o o o o &p >p Yp up p p p p p Fq Vq q r r r "r Br Dr r r r s s s s s s s s t Dt Kt t t t t t t t t t t &u (u Nu Ru Zu u u u u u !v /v 2v 6v 8v qv v v w w hw qw w w w w w w x x x x wx yx x x y y y y Bz Dz Fz ^z `z bz z z f{ | -| | | | } 4} 6} i} m} } } } } } } } ~ ~ &~ G~ O~ ~ ~ ~ ~     # ' = ρ g   1 ? ߆ y ~ ͇ C ӈ ! i  J ̊  W ċ ȋ ԋ ׋ ً ۋ 3 C s ، ی % ' H i n  8 Ƒ ` x & ŕ . 3 F  ]  u Ι &    " `  4 7 9 f  C F j n ˝  О  D c g Ɵ      \ ^ Ҡ 1 X = |  1 3 M O ~  K M { } Ӥ  8 v   F l Ѧ h . 0 q   ; x z @ ߪ ( * , H J - 0 w z ׬ ٬ 6 8 K N Q S   ? { % ( Z ԯ ׯ # S V X װ ۰ ݰ 4 T W ~ 3 5 S W Ų Dz  H س ڳ    ; h l 1 K P  , l n z  Ƿ D a g > @ e ǹ ( f n y º ĺ  9 ǻ $ c e ¼ ȼ ! ' , 0 3 Z ] _ Խ ׽  Y 6 s ۿ  H [ _ a & 9 = ? 9 L P ~      H L ^   9 a , s u  . 0 b  / 1 f ~   V + W  X   + d , . 0 F n # X Z | 7  6 8 f k  + > D O V i l n R 6 8 _ f     P  C j n I s w ) p s M P R . R V  X [ ] _ 4 8 n  X _   L  6 l q u x z  A Y f i % b     9 > E H n r D l r ! % Z ^ " & c + / 2 5 q u   1 W  y  a   L O % 2 8 : x . h o r t   _ j n p  F I K " G N  [ ^  & B H     X  : A I  ( + ? x ! A E U  H g j   / F Z a   # & ( E k n  ? B p Y  / P p    @ T [ h  ? j # N y  D o q }  D o  F q      6 a      $ O z |    ( * ; f       : < g       G r     I t v     3 ^       I t v  : e ' R } ) T   + 2 7 < P S U W 1 5 g             F p        " q s      Y ` y        8 ? X _       , 3 t {        ! # V    " W   , 0       # %         B D l p           0 4 6 Y `         ; B }          q     p         7 ; L         $ V       ( 7 i k      ) 7 i k d! ! ! " /" 2" z" " " " # # # # # # !# @# q# # # # $ F$ $ $ $ $ $ $ 5% e% h% % % % & "& $& 6& :& h& k& }& & & & & & & & & & & & h' ' ' ' ' ( %( '( 9( ;( b( d( ( ( ( ( ') )) +) `) x) ) ) ) * =* {* }* * * /+ 1+ E+ + + + , c, , , &- g- i- - - - '. Q. T. V. . . . . / / B/ D/ / / / 0 0 0 0 0 0 1 >1 B1 D1 1 1 1 1 1 1 ,2 i2 l2 2 2 3 3 3 3 L3 j3 3 3 3 V4 Y4 4 4 4 5 5 c5 5 5 5 5 5 )6 R6 6 6 6 6 6 6 6 %7 7 7 7 7 7 7 Y8 8 8 8 8 8 8 ,9 /9 L9 r9 u9 w9 9 9 : : 8: Z: ]: _: a: : : ; ; 7; ; ; ; ; < V< X< s< v< x< < = = Y= = = = > > > > > U> X> > > > ? 3? s? y? |? ~? ? ? ? ? (@ @ @ A A A A ~A A A A A _B zB ~B B B B B B B B B C 5C 9C C XC C C C C C D JD LD D D D D D 4E QE oE E E E 2F 4F sF F F F %G 7G _G cG dG eG tG xG G G G G "H fH H I II KI ]I _I vI xI I I I I J J FJ fJ J J 2K cK K K K L \L L L L L 7M hM jM M M N N IN bN N N N N O O hO zO O O O O P *P -P XP iP lP nP P Q yQ Q >R R R R R R R S S 7S ;S VS rS vS }S S S S S S S +T -T HT KT MT T T T T T T U U U U 5U MU QU XU \U sU U U U U U U V V V BV iV V V V #W GW kW W W X bX X X X X X Y Y ;Y >Y @Y BY {Y Y Y Y Y Y Z Z Z LZ tZ Z Z Z Z Z Z Z Z [ h[ k[ [ [ [ \ \ \ d\ \ \ \ ] ] ] H] t] ] ] ] ] ] ] ^ ^ F^ M^ `^ c^ e^ ^ ^ ^ ^ _ _ _ O_ _ _ _ _ _ .` 2` M` Q` ` ` ` ` a a a $a +a /a Aa Ea Ha Ja a a a a &b 9b j   # K O ] a c e ߈ 0 4 m x   _ Ê NJ ׊ ۊ ފ   F t ) , X $ ( M P s w Ǎ ˍ ? D M R Ď ݎ D G   } ؐ ې 2 5 6 7 M Q ّ  L |  d ˓ M & i  & B D ֖ ؖ = ӗ  V  E G t ̙ X u x ߚ + l n ˛ - / S x Ԝ ֜ + - ǝ U W  ; ] ` q s ԟ  , @ f Π  4 ` t ơ ڡ & : a Ţ  ! F Z x գ  4 [ o Ƥ  / R | ե 2 F d  E Y Ƨ  ) G l ˨ ߨ $ 8 X      ! # % H K r " & ( V n r ݫ / D |  ج ۬ ݬ ߬  ) Z ] ̭ ޭ L O Q S ˮ ή     F w ݯ  B E s 0 v α  g 9  ? C E S ص  / 5 Q X ] p ۶ " & s w z ۷  A F [ ޸  0 G L N P ƹ   C c º 5 O Q }  R C 1 ƾ ݾ   7 : b ڿ ܿ * , > A C E y ) , U   - [   I h j m o O W \ X \ n q s u   X / f $ ' B E G I  , / f  0 ; C K | 0 ` F I |    + . / 0 ) / I d j % Z \ u . 0 2 g : < h j    j m o 8 r " \ 8 r u w  ! % 2 ] v { 0 5 Z ^ a c  2 6   $ Q T ) - 0 2 C D E U Y v z  : p r t  H J t  l o q   a  = @ B n q  & , R X D  R  A C E  Z \ ^  ` d  B H 5 B H M Q T / : > A v z . S V  / _   2 P j o t x z  B n r  O U l r w y . `   * . 1 Z ^ { ; z }  < @ [  , / 0 1 C G c g x + O 2 w F F D x  h f h 6 z | 0  =  : c & e 8 t DdAEjln7:]`uyOTXZH{;=ot.fhr[E c     9 Z ^   F X ]         4 7 u   & r   (vx 02[]|(,r}  tLNv ACfhx{;?1cy~4":?Cou"$'Zz~+/1ac 5hm2?T ]          !!!;!!!!!!"$"&"{"""6###$$&$$$`%%%&&F&n&&& ' '!'#'8'<'~'''''''''l(o((((((((U)X)f)x)))))))E*]******X+[+i+}++++++++,!,$,I,M,i,,,,,- ---[-^-r--------..4.8.;.`.d......//(/+/-/////00Y0[0o0r0t0v00000000000021J1s1122222223W33333333G4s4444455;5?5E5S5l5s55555555 6*6.616>6V6Z6z6666666666@7l77777 88.82888F8_8f888888888889 9(9,9/9?9B9D9F9a99999::C:E::::;B;F;;;;;;;;</<`<d<<<</=5=>=D=e=k=m===========$>>>>? ?:?=?????@R@e@k@@@@@@@@ A%A(A+A?ABADAFAAAA7BBBBB CC C@CcCCCCCCCDDDDVDuDD EWEZEiEEEEFF8F?FFFFFF#G.GyGGGGGG4HqHHHHHH I7IBIhIsIIIJJypyyyyyyz(z5zjzzzzzzzzzzz {{{D{T{i{{{{{{|2|B|O|t||||||||||4}J}L}_}b}d}}~~~~p[^!$́ρ>AC܂߂LՃ!(+-~DŽC~х Nvy{}DGXyчUXZ <>Hb|~ s݊ h|au|Ōތ8QTV7:[׎/Տ doɐː WZ‘đƑRU^wђՒ Fw>Anr \w{#N|ܗ,dh˘#&6]vؙ :kmܚbruwܛߛ=@gל8Mv*-T6La  #JNa a֡LNܣޣ3   ϥӥإX[vϦԦ:Z]auy֧ڧ bfy{  #uөթ-/Fa{}ikn%yŬq̭ [FT[x{}֯ gj߰]%(*,9<aIJ%6=?}ų߳:QU`ĴE\IcMg%'6ɸ3\giw޹"N`E^dŻջ׻ٻ!Zּؼ 9a˽+cþž߾  Bÿտ!0[hlsw(59EHJLfi +/s WZTV(/GmWbd-UYD ?KPR#(V  9m)\<@BW0~>W/VY[]vy;cez|S^e%146CF(*;>KNt@DPbEG~GI*M9|~KOa,gi,ln  ,.cjz25O`t XJrE\_`acdegvw~ !#03j   "&W[n24Kaz|>egik}IKMzFHm)W,.0Bo!=n?p8s0oqs"O~Bk7m8bdfhx$&Si|[] X.|1dO1whI-wy LN{ Vg 3d$'K|,/[p&NQy)HWZ\),;OU;m  , `      8 W Z t     9 _ z }    ! # V Y   , 0 N y        ;>s /24X[ #%'KgjY$')u %(cj47VpCEil/69;>b3>&^#%y#'>c$<DGIj  Xb<@ae{03<?UX| S i       ?!\!`!!!""7"p"""""""""%#W####$R$Y$d$$$$$$%%%;%>%@%%%% &>&@&&&&"'%';'_'''''''(A(D(M(P(q(t(((((((((G)Z)))))*\*****+9+P+S+U+r+u+++++++++,,,g,z,,,,- --X--------=..........//8////////0 0M00000001G1u11111 232d22222 33,3/3133333333244464v44444 5*5,5d5y5|555555"6j6n6666666J7L7b7w77777788'8)858I8f8q8s888888888879I9999999+:/:6:::x:|:~::::::::::::;;;;;;J;L;;;;;;;;7<:<;<<<G<K<`<b<<<<<<<<<=/======2>5>6>7>O>y>{>>>>?:?s??? @?@i@k@@@ A=AoAAAB;B=BrBBB C>CnCCC D D@DsDDD E^^^)_{__`` `G`J`p```````aa^abaaaaaaa>bBbbbfbbbbbc c=cAcccccccdd`dddgdddddeeeDepeeeeeeee"f&f5f9ftUtbtetttt]uruuuuuuuuu#v'v9v;vHvKvvvvvvvvv ww0w2wqwuwwwwwwww,x3x5x8x9x:x\xxxxxxxy y=y@yXy\y~yyyyyzzyz{{6{:{{{{d|i|m||||||||A}V}}}}4~8~J~v~~~~~~~~N  !%X\pr΀Ѐ݀< ]a'Z׃?CFGHY]~gi1WZՆ׆/2tЇ 'VZFtz|ahϊV͋8:_܌ތZÍƍɍʍˍ:<aԎIloqvȐilnÑ!QUʒؒ*.?c̓  57o!j͕AĖƖ$ԗ8;>vy|ݘ1LOPQae ?adef{Κ>Lbf(WmrÜŜǜɜ 'n"-Rޞ'U(,/01DHfhա ILf£أܣ?Ӥ13.n`Ƨȧ3hswyŨRߩBFHr}ͪBDjoͫҫԫ,SpŬǬȬ۬߬&*:=SVcf9cg}Ʈ !rx7ioưSP˲ϲ Yó;=VXfiƴʴմٴܴ356OPkoõܵ޵!"#CGöƶ!^bsuҷշַ׷6:KMfhux׸۸04IKdfsv۹߹37LNgivyպٺ+-FHUX -0befg¼Ƽ׼ټ;>?@Y]ʽ̽ٽܽ/3pt@DUWprѿտ')BDFSV'*Z]^_}3678VZ /3pt HL]_xz|"35NP]` "$14cfgh2567VZ 04qu HL]_xz"&79RTad,.;>twxy13MP/1JLfi JLeg $6ce~W[p@DSVWXtx/2mpqr,.HK&(AC]`=?XZtw'TVoq"&8eg59Jwy IM^8fIKdf*Gk (*DG .I} FIJK\`"=Um*AXp%@\x)A_z6VX\nnJ)?A{RKFH_aK2+-zegW-/n+j(g$c"aZM4cfh!CFbY w5<?Y4nqs-?B~?dhk!$&(Im lnl>ILt)46_ #Oh)`3 ~     8 C E p      ) e p r      H       G   9} F3t8^doqITY >~,hswXcer%MPbt  /NR-02q-),E;>9@9@N;    !g!!!!#"w"""""#|##.$0$B$$$$$%z%|%%%)&y&{&&&'e'''''(p(())))),**++++i++,a,,,,&-w----...,///D///E0H0I0J0d0h000000111!1Z1]1^1_1x1|111111222252m2p2q2r222222 33(3*3D3G3~3333333334484:4T4W44444444453555N5P5j5m5555555 66!6N6P6i6k666666666#7'797f7h77777777778>8B8T8888888888899Y9]9o9999999::::O:o:::::(;U;W;p;r;;;;;;;;;;;;<<'<)<6<9<`<<<<<<<<<==== =7=9=;=H=K=g======>>;>B>F>I>J>K>f>j>>>>>>??,?.?0?=?@?????$@C@F@G@H@b@f@@@@@@@@@@@@ A#A@ACA]AAABBBB5B9BhBlBBBBBBBBBBC?CBCCCDCbCfCCCCCCCCCCCD9DSDVDWDXDkDoDD1EEEEEF|FFFFFFG G'GNGPG^GGGGHJHMHHHHHIIIKIoIsIIIIII JUJUSU^UnUUUUUUUUUU VV,V=VQVbVpV|VVVVVVVVWWW,W=WHWXWkWWWWWWWWWWXX X+X3X@XUXmXXXXXXXXX Y#Y1Y>YSYcYrYYYYYYYY ZZ(Z6ZEZZZiZ}ZZZZZZZ [[6[Q[_[p[[[[[[[[[\,\9\R\h\}\\\\\\\] ]]&]7]U] @0000000000@0@0@0@0@0@0@0@0@0 @0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0 @0@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[ @0 @0@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E@0E @0 @0@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq@0Lq @0@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O@0O @0@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R@0R @0 @0@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h@0h @0@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz@0gz @0 @0 @0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0 @0 @0@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u@0u @0 @0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0 @0 @0@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05@05000000000000000000000000000000000@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tT@0tTH 3 \  . E ?fи:C`t+2=vh"E=ZR*= =R;eci$f(YtȊo)-#G-D@JWT]}FC) &.N8OZecmx7_Y1NW\qߪ&%3 EP Mo L I \ 6 X 0   # * n  H } @  :' E p ._ ~*wv,gc 7KK`o[36789:;<=>@P]kx     # * 1 ; B J Q W ] i s z        % 3 7 : = B G J M Q V Y \ ` h k n q v |   - 4 B Q [ e o |  % 4 A I X d k {   ' ~~uX #v&=),B0p258^=?BAFIMNeQTWZ[]`%d fhkpt.xA{U~Z̈́ue ̠֣*غheMCnmVD:]mH @^ u$'*-f038:<>@tCEG{IJLNXQSWVTX(Z<\:_b#eik ohqku)y2}>эnfqԝ~ͩR.&c{F$#7  /eD#)/%6v<AoGLkRW\?bgls=y~2t՗Eaoi1RxoZ3  $(-27;@>FJOT0Y]bhTmsqv{<ل _xS.u2$^;'c U$**0Z68;N=a?AADFKbMORKUXV[]`Xdfhrlpsw{[˂L@ؘ ޥsb;,N[ZYiD; 8z)D."k$(*$.q2.7V;=>vArEHCKNQLTW[]`^ei mqul{B}"h§M)4lcAst0Xa v40p"%),15y8<@EJzOWTW[^Uc"gFj n#quxr{~`ʏƥҬƱ?V~kP- 9|#|(Y-047V<?ADGKzOSW\afk$nr|ugz{}V\b݇Ɖ׏ `~ $ 8@A aVFr 4\E $(-137`:N=R@BFIJMQOQ STVXZn\0^*`bdgj"mnpOs7vys}s͋jJMT<1VfOB# g 1 w     F! $ ' + C. 0 14 7 : = A D I K 6O R FW [] Nb f h k pm bp Es &v z 7~ ΄  l R D Õ b  P ܷ    q  O 2 g    ` # ' /+ y. 2 5 {9 < z? +D H K P T _X ] a e l p v xz y R Ñ ` ϖ p  p į  y  @ 2 g w A m N G   @   n$ ]( R, u1 6 < ? B gE MI L N 6R T V oY '\ _ h r y {| e M  G l V w ּ 8  | J  ,  H      $ 3# ' + 0 5 F9 < p@ C _G K N Q U X G\ _ d jg ~k Wn Pr vu y W}  X G ב  i r 5   _ ? B 8 q  S ^  F    ] n `! # :' .* {/ 2 5 : v> B BF %J M P U rY ] ` -c f i l o p w z }  9 œ  2  0  5 ج y   Ƽ 9  : 5 : | :  $ <O |M%(,.0y47:~<?HBD GI/M$P{TWD[_beilr#x|QdžT֍XHkűpeC=m6i0S+.n ft"H&)+a//359;9?xBDFHuLQVZ`jf*l*oqs0vxyA{_Š~͙x2 ƽ-Ni8To,z`acL  9$(/$5O<?>^@uBD2GHJLIOQ}UX[]`GbdeYo[4?ABCDEFGHIJKLMNOQRSTUVWXYZ[\^_`abcdefghijlmnopqrstuvwyz{|}~                      ! " $ % & ' ( ) + , - . / 0 2 3 4 5 6 7 8 9 : < = > ? @ A C D E F G H I K L M N O P R S T U V X Y Z [ \ ^ _ ` a b c d e f g h j k l m n o p q r t u v w x y { | } ~                     ! " # $ & ' ( ) * + , - . / 0 1 2 4 5 6 8 9 ; < > ? @ A C D E F H I K L N O P R S T U W X Z [ ] ^ _ a b c d e f g i j l m o p r s t u w x y z { } ~                          ! " # $ % & ' ( ) * + , . / 0 1 2 3 5 6 7 8 9 : ; < = > ? @ A C D E F G H I J K L M N O P R S T U V W X Y Z \ ] ^ _ ` a b c d f g h i j k l m n p q r s t u v w x y z { } ~                           ! " # $ & ' ( ) * + , - . / 0 1 2 3 5 6 7 8 9 : ; < = > ? @ B C D E F G H J K L M N O P Q R S T U V W Y Z [ \ ] ^ _ ` a b c e f g h i j l m n o p q r s t u v w x y z | } ~                          ! " # $ % & ( ) * + . n[512Re2679Yr 59:<\s378:Zm/346VoDnT] X%X%X%X%X%X%X%X%X%X%X%X%X%X%̕X !!8@0(  B S  ? _Toc159540233 _Hlt159533494 _Toc159538454 _Toc159540234 _Toc159538455 _Toc159540235 _Toc159538456 _Toc159540236 _Toc159538457 _Toc159540237 _Toc159538458 _Toc159540238 _Toc159538459 _Toc159540239 _Toc159538460 _Toc159540240 _Toc159538461 _Toc159540241 _Toc159538462 _Toc159540242 _Toc159538463 _Toc159540243 _Toc159538464 _Toc159540244 _Toc159538465 _Toc159540245 _Toc159538466 _Toc159540246x[[..:q:qOORRhhizizgg66vTvTU]@ y[[EELqLqOORRhhwzwzuuMM}T}TU]DDDDDDDDDDDDDD³DóijDųƳDdzȳDɳʳ˳̳DͳγDϳгDѳҳDӳԳDճֳD׳سD ٳ ڳD ۳ ܳD ݳ ޳D ߳ D  DDDDDDDDDDDDDDDDDDD  D! ! D" " D# #D$$D%%D&&D''D((D)<<<< !<"#<$%<&'<()<*+<,-<./<01<23<45<67<89<:;<<=<>?@<A|BC<D|EF|GH|IJ|KL|MN|OP|QR|ST|UV|WX|YZ|[\|]^|_`|ab|cd|ef|gh|ij|kl|mn|op|qr|st|uv|wxy<z{<|}<~<<ŠŠ<ÊÊ<ĊĊ<ŊŊŊ|ƊƊ|NJNJ|ȊȊ|ɊɊ|ʊʊ|ˊˊ|̊̊|͊͊|ΊΊ|ϊϊ|ЊЊ|ъъ|ҊҊ|ӊӊ|ԊԊ|ՊՊ|֊֊|׊׊|؊؊|يي|ڊڊ|ۊۊ|܊܊|݊݊|ފފ|ߊߊ||´|ôĴ|Ŵƴ|Ǵȴ|ɴʴ|˴̴|ʹδ|ϴд|ѴҴ|ӴԴ|մִ|״ش|ٴڴ|۴ܴ|ݴ޴|ߴ|||||||||||||||||||||  |  | ||  |  |  |  |  ||| |!"|#$|%&|'(|)*|+,|-.|/01|23|45|67|89|:;|<=|>?| @ A|!B!C|"D"E|#F#G|$H$I|%J%K|&L&M|'N'O|(P(Q|)R)S|*T*U|+V+W|,X,Y|-Z-[|.\.]|/^/_|0`0a|1b1c|2d2e|3f3g|4h4i|5j5k|6l6m|7n7o|8p8q|9r9s|:t:u|;v;w|<x<y|=z={|>|>}(***i,!-<<8=p===AB?BpBBFF H1H8KLKKKKLILLM^e fs39G1Eu.o/[Z} CGqs~tuy{:k?Pd4g9 K F&8&m&()).5':@ABCGKMNPP%S+TTV>XZQ[Rckde7giikkooEtWttu-u{uuu2vrvvW{h{{N|y||}A}p}}}}~~1wѩBS& 2 < < > @ I J J % 8  9 d ޝ d [ g g g }" rB B C t t U g   D U & & ' G G G -H rH H I e 0e ie e e !f Ff sf g g h h h ?i i i i Lj xj s t t  O  Ē ! g Γ  P l M Z  O  ] p 4 V ; M Q K ) s {~0;1S1|112fLxLLMMM!N``daaaabbc.cWjq$1Ym;<8iejm~p4t0v~wxA~gɄ6Hn1^!kC?B#ϼ}M}U+~U/  &-?fy0/ABSVg%|?eww"U00112233456*607B7K8]8f9x9:;1;<=>>L?@wBBCEEE)FFGtKKLMM,Q>QQU]      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ W > 2 l  #1#&':'')P.22279;; <\<^FoFFFM$U6U] ^4^ddReRegghunx~x{{6ȇTpSԎ,қ<LQoݹZ%Qn* BC W O x  [""v&2D345m?@ABCEeOQStTsVVYg^w^a=eg_kQoztu۹ Kc0(W(RYY\]@`c"p@z] O7[   foBr 3#G#Z##$H&Z&&$'''E(***p,1-<<?=w===BBFBwBBFFH=H?KRKKKKLQLLM^ffs>@Nƺ;Q%{/o7$aa CGqstuyArEWk<n@ R M &?&t&()).5/:@ABCGKMN%PQ-S3TTVEXZX[Ycsde?giikkooLt^tt u4uuuv9vxvv]{n{|U|||}H}w}}}~~~8~ةHZ& 2 < &< > @ I J J - ?  ? j  k [ g g g " zB B C t t \ o " ! J \ & & ' G G G 3H yH H I %e 6e pe e e 'f Mf zf g g h h i Gi i i j Sj j s t t V ˒ ( o ֓  W s T b  V  d v ; \  B  T W R / z 0B1Y1112mLLLTMM(N``kaaaabbc5c_qw+9`t;<?ikjnp>S?@~BBCEEE0FFG|KKLMM3QEQQU]  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~=*urn:schemas-microsoft-com:office:smarttags PlaceType=*urn:schemas-microsoft-com:office:smarttags PlaceName8r*urn:schemas-microsoft-com:office:smarttagsCity9t*urn:schemas-microsoft-com:office:smarttagsState9u*urn:schemas-microsoft-com:office:smarttagsplace8*urn:schemas-microsoft-com:office:smarttagsdate *1101112131415161718191995220200120022003200420052006200721222324252627282933031456789DayMonthYear(#'#)(!')(!')(!' )("')($')($' )(%' ))'( )'(&)'(&($' )('&)(')("')(#')( ')('&)(')(')(#')(#')('$)(')(%')(%')('$)('%)(#'$)(')(%')('")(')(')(%')(')utur(!')('#)('#)(')('&)(#')( ')('&)( ')( ')( ')(')(&')(#')(#')(#')(&' )(%')(%')('!)($')(')(')($')($' )(')(')(!')(!')(!')("'!)(')(')(' )(')(')(')(')('&)(')($')(')("')("')(#' )(')(')(')(')(')( '#)(')(#')(')(!')(!')(!')($' )(!')(!')("'!)($' )(!')($' )($')('$)(#')(&'&)(#')(%')(%')(%')(%')(%')(%')(%')(%')(%')(%')(%')(%')(!')(!')("'&)(%')(' )('&)(#')('$)(' )('$)(&')(#' )($'#))'#(&)'(#)'()'(&)' ()' ()'(&)'( )'($)'()' ()'()' (&)'#(&)'(&)' ()'(&)' ()'(&)'(&u)'($u)'(!)'(#)'(%(%' )(%' )( ')(')( ')(' )(')(' )( ')(!'")(&' )(')(')(')(')(')(')( ')( ')(')(')(')(')(')( ')(')( ')( ')('")($'%)($')($')(&')('")('#)('")($'%)(%')(&')(%')('")("' )($')($')(%')(%')(&')u($')(&' )('")("' )($'%)($')($')(&')(%')(' )(')( ')( ')('")("')u(')('")( '#)( '%)( ')( ')( ')(%')(%' )('")(%')('")("' )('")(')($'%)(%')('")('$)("' )(&' )(')($' )(')(!' )("'%)('%)(&')(&'")(&')(')(')('#)('%)(')(')('#)(')('%)(')($')($')($')($')(#'#)(#')(')(&' )(')("')(')(!')(!')(&' )(!')('$)(')('&)(')(')( '&)(')(!')(')(' )(')( ')(')(!')(!')($' )($')("')(!'#)("')($')(')(')(&')(!')(&')(' )(&' )(&' )(!')(%' )('%)(')(')(')(')(')(')(')( ')( ')(')(')(')(!' )("')(')("')(&' )("')(#')(#' )($'$)(')(')(')( '%)( '&)( ')('#)("')('&)("'")("')("')("')("' )(#'#)(#')(#')($')(&')(')(')(')(&' )(&' )(&')(')( ')(!'")('%)(%')(') ('&)("')("')("')(%')(&')(&')(')(' )(' )( ')( ')( ' )( ' )(')(')(')(')("')(!'%)(')(')("' )(')(!')(#')ut(&')(')(' )(' )(')(#')(&'%)(&')(&')(&')($')(&')(')( ')("'!)("' )(%'%)('&)('!)("'")("')(#'&)(#')($'$)(%')(%')(&')(&')(&')(&')(')(')(#' )(#')($' )(%'&)(&' )(&')(&')(')(')(!')(!')("'!)("'")("')("')(&' )(')(')(')(')(#')(%' )(!')("'")(' )(%')(' )(')(!'&)("')(#')(#')(#')($'!)($'!)(!'#)(!' )("')("'#)("')(#')(#')(#')(#')ur($')($')($')(&')(&') ('#)(')( '$)( ')( ')('#)('$)(')(#')($')(&')u(!')("'!)(#')(')(%')(&')(')(' )(&')(&')(&')('#)('$)(')(')(')(' )(' )(')( ')('%)(')(')(%')('$)(')( ' )(')( ')(&')( ')(')('#)(%'&)(')(')(')('#)(')(%')('#)("' )(&')(&')(&' )(&'")(#')(%')(%')('#)(')(')($')(%' )(#')(#')('#)(%'!)(%'!)(%'!)(%'!)(')(')(%'!)(%'!)(%'!)(%'!)(%'!)(%'!)(%'%)(%'%)(%'!)(%'!)(%'!)(%'$)(%'$)(%'&)(%'&)(%'!)(%'!)(%'!)(%'!)(%'!)(!')('&)($')('&)($')('&)($')('&)(')('&)(')('&)(!')('&)(!')('&)(!')('&)(!')('&)(!')('&)(!')('&)(%'%)('&)(%'%)('&)(')(!')('&)(')(!')('&)(')(!')('&)(!')("')("')($')(%'!)(%'$)(%'%)(%'&)(')('&)(%'$)('&)(%'$)('&)(%'&)('&)(%'&)('&)(!')('&)(!')('&)(!')('&)(!')('&)(!')('&)(')(!')('&)(#')(#')(#')(&')(&')(#')($' )('%)(%'#)(')(%' )(&')(&')(' )(&')(' )(&')(%' )(%' )(%')("')("' )(&') D&K P o t   , / M P q t  (+KNnq"$9<=S[^`cdt|.9x#.mxQ\ +8;<RZ]_bcs{~'2u*grHS{367?ADERcfjvz  'T_`kr  &S^_jq~ nw "+<EHQR[x'3:+8DZcls $CS   D M ] ^ a w *!0!B!K!!!""$#)#Z#_#c#p#~#########$$$$$$*$;$>$B$N$R$y$$$$$%%Y%g%h%q%z%%%%%%%%%%%%%%%&& &&.&/&2&4&;&=&F&H&N&P&_&p&}&&&'$'Z'n''''''((((<(E(a(b(e((((() )")2)H)O)Q)T)U)a)o)v)z)))))))))))))))))))))** * ***$*2*=*>*J*^*j***!+(+f+o+,,, , ,,,,u,,,,,,--..C.H.a.q..............////'/B/O/W/b/k/t/}////////////0$0<1E1|11111122\2b222222 33%3;3F3O3X3a3m3o3r3s33333333333333344 44444"40414<4G4S4T4Z4\4n4o4w4y44444444445!5h5q555555555555555556 66 6B6I6L6U6V6_6k6~66666666666666666+707Q7W7y7}77777777777777777788 8888,81878>8B8G8U8Z8^8}888888888888$9*9]9a9999999999999999:::::::!:):b:f:::#;%;K;T;;;g<w<<<<<<<<<==/=9=M=X=Y=b=q=z===============>>>+>,>6>8>=>O>\>]>d>f>v>>>>>>>>>>>>>???"?)?0?1?8?K?^?`???????????? @@@ @"@2@O@Z@\@c@t@@@@@@@@@@@@@@@@@AA2ATA^A`AcAdAmA~AAAAAAAAAAAAAAAAAAB BB'BFBPBSB_B`BiBnBvBBBBBBBBBBBBBBBBBBCC CC!C$C1C3CVHVIVRV]V`VnV~VVVVVVVVVVVVVVVVVVWWWWWWnW{WWWWWWWWWWWWWWWWXX XXX X)X6XCXDXMXXXXXXXXXXX YY4Y7Y8YDYGYUYVY]YjYkYnYzY|Y}YYYYYYYYYYYYYYYYYYYYZZZZ"Z#Z,Z9ZEZLZ[Z\ZeZZ [[ [/[2[5[J[K[W[i[y[z[}[[[[[[[[[[[[[[\\ \=\@\D\P\T\{\\\\\\\\\]$]2]E]\]c]r]y]|]]]]]]]]]]]]]]E^J^Z^d^{^^^^^^^^^^^^^ __&_L_P_|________` ` ``` `+`7`?`L`N`S`U`d`f`k`}``````````-a1aDaIaLaZa\a`akatava{aaaaaaaaaaaaa-b3b?bFblbsbbbbbcc?cBcCcPccccc-d7d>dMdPdXd[dddudxd|dddddddddddddddddeeeVe_eve|eeeeeeeeeff;fGfXf^flf{fffg gggggggggh h;hGhhhiii&i.i5i>iEiNiWiYi\i]ijisiziiiiiiiiiiiiiiiijjjjjj%j'j.j0j9j;jHjJjQjajijqjxjjjjjjjjjjjjjjjjjjjjkkk'k4kTk]k`kmknkwkkkkkkkkkkkkkkkkkl lll'l.l1lFlGlRlSlZl`lklllsl}lllllllllllmm mmmm#m-m1mcmjmmmmmmmmmmmmnnnnnn'n(n/n5n@nAnHnUnYnunynnnnnnnnnnooo"o/o0o;oy@yCyDyTybyhykytyuy{yyyyyyyyyyyyyyyyyyzzzzzz.z5zBzCzIzKzUzjzyzzzzzz{{{{{||I|P|Y|g|v|}||||||||||||||||||}}}}!}D}R}o}}}}}}}}}}}}}}~ ~ ~~~+~,~3~5~I~[~i~~~~~~ ).DT€ɀ̀Հր݀ '5@knowzÁсԁ݁ށ $45<>LNU^iłт܂݂MZ[ikσЃ؃ڃ &(/6Afmnu'Y`fstׅO_5; ".2Ybrsv{͈PVHLdh΋ۋ  #$*;>BNRyόЌӌ،ތ"#&FKakz}~ԍ  &07CJKNTpqxz}ǎ̎+/V`ktz͏ڏIOT` CL^e$R[r~ɒʒ֒ؒޒ"%Yb%.7>@CDHJMNS\_`ilxyŖΖіՖ8=IRUYchxݗ8GILNVjqȘ՘ =Fszknosśʛ "$'(,.127@CDMP\]fknox{ƜϜҜ֜!-69=GL\ehqʝ͝ѝ*,/19MTkvw~Ğ JOo{V_kyĠŠΠРӠԠ۠ 7EJdksz{~Ρޡߡ  169Bjor{|â29ǣˣ)+2W\_i|ʤۤ!EMhqХ٥$TYVYWYgYiYkYZ[[[f[g[m[[[[[[[[[[[[-.45:GIJCC!C#Cnhowoooooppp$p%p-p@pFpIp\pipoprppppppppppqqNq/:CNdinv{$-8OZ^dqBF AI*2ptw-7fpw!(AMrz "'06 m!0:]`#19=FL*3'7S]iors5?H(/145@ $-RW0  *;eiqN]d dsyHV\_lmsy#,io #~ms~$js/23FNWdi 3;@_jox}# !$%8@G"$/;DZabi GTUc=PyJlr!(/145A JO|!,/"2,fr *347z '(129GU]d )t#),-@V]fgn{I <@4=2=MRUViqu~ w        ) ; > G I S b k m      E J V Y      {     x t?I]amnxz}LT~Wz}~ !$&.CJ !')/8<LP]i;<GHSU[iw~;HIPR[lr (17@GhkH X c   ###4#7#8#>#A#L#M#R#T#]# $$$#$'$4$C$K$T$]$c$l$s$$$%&&U&`&-(p(y(((((((((%)+)-)4):)>)L)S)))))))))**0*2*5*6*@*R*V*n*|*F,h,t,},,,,---4.S.Y.b.r.}...M0X0f0r00000001111v1|1112 22222 3333%333344 44$4,404245464?44444445555556 7 77g7q777k88888888888888 99_9h999::3:6:7:J:K:N:O:X:Z:]:^:h:{:~:::::::::::#;< ===0=;=D=M=b=m=w======????????????@@@:@E@i@t@@AAAABBBB B+B3B6B7B>BAB]BCCCCUIUJURUSU]U^UmUnUUUUUUUUUUUUUUUUUUU V VVV+V,VYRYSYbYcYqYrYYYYYYYYYYYYYYYZ ZZZ'Z(Z5Z6ZDZEZYZZZhZiZ|Z}ZZZZZZZZZZZZZ [ [[[5[6[P[Q[^[_[o[p[[[[[[[[[[[[[[[[[\\+\,\8\9\Q\R\g\h\|\}\\\\\\\\\\\\\\] ] ]]]%]&]6]7]8]B]D]P]R]U]D&{~  & + G L k p "'EJhm9<|  .9KPX\x#.>CKOmx$,0Q\mr8;{~ '2DIQUu*:?GKgr%)HSdiwy )-\b(r'qgm5;qwIM}CT M ^ !&!q!s!!!""""##4$:$$$$$%%U%W%z%%%%%%%%%%&/&y&&&&''''''E(b(((7);)h)n))))))*****!+(+f+o+++++u,,,,--..w.{.....L/P///0051;1u1{11122V2[2*3.3333344G4T45555566 666:6B6I6k6666+707Q7W7y7}7777788>8B8}8888$9*9]9a9999:b:f:::#;%;/;?;K;T;;;<<==m=o=======>>O>]>>>>>>>??K?_??????? @@O@[@t@@@@@@@ACAGAwA}AAAAABB?BEBBBBBBB$C2CCCCCHDLDDDDDtE}EEEFF0G4GGGGGGGHH{HHHHHH$I3IeIiIIIIIIIEJKJJJJJ5KBKKKLLtL|LLL0M9MMMMNBNENWN]NNNNNO"O6ODO^OdO|OOOOOOPPPPlPrPPPPPQ#QPQ]QQQQQQQRRKRPRRRRR/Sbebkbbbcc?cBcccPdZdddddjereeeeeeeefKfPfwggggShXhiiiiiijj\j`jjj kk#k%kTk]kkkkkkkkkkl'l.l}llllll-m1m`mcmmmmmmmmmunynnnnnnnnnooMoQooorooooooooopp8p;pVp]pup}pppppppqq5q8qqqxqqqqqqqOrUr`rbrrrrrrrrrssLs`sssttKt_tttIuQuuuuuv%v1vJvjvovvvvvvv[wawwwwwyy[yayyyyyyy5zCzzzz{b{c{{{8|<|o|u|||||||8}A}^}b}h}n}}}}~~,~~~~ gh&.uy X^kn$5M[^cftׅO`bsΈ4:Ќ#&ptۍ'-TqFT`ǑaeʒRX֓ړ̔Δ$)}\_Öޖ46IR_atvԗؗݗ8H6<lrkn ad@CknœĜ-6CEXZyʝ+ JRk{@B^`s{ȡΡ 16]ajo29*;?PVv|ۤɥϥdhߧ08bj{Ѩ֨ۨߨ&;SXpuթ۩8;īȫ#ag3Glpx{ԭwzѮҮ^e|BDdj|ױ25xȲβݲ36?B[]ͳѳֳٳ=A >@XamoεԵ+?hmǸ &%k~ܺߺgk+1QWNTGK־ھ !^eοҿKMls*1 FM,3swNRcjpvEHpsVc#*nrDT,8 =C]cps#LV~ !NQoqIL(9>BD[]HJfj.26>TZtv$0ioy13#']cz$/6QSnp PRnp$&OSimqu >BX\`dy{YaryHN{RTqs46Y[z|68OSnqgAD.1[a!*/EKv| ),W];A )[pV_|3>QWnt-AH^bj )nsx|49>EK` +OTao "(beTc+/|JO~@G~4;uy<>7A <c g           = A         " ' 8 > q s    LS{3:x|&lpMQ JN>Bcj#4;_a'+>B"%SV4;9?6:v|'6,0W]  l r   !!q!t!!!!"q"t"""C#G#########$$1$=$w$}$$$$$$${%%%%%% &&&&&&''R'T'''''''''((2(6(A(G(g(m(~(((( ))4)@)m)w)))))4*L*o*q*****1+3+P+T+m++,,4,D,l,{,,,,,,,"-%-O-[-----Q.S....."/$/A/E/t////0090G00001>11122'2-2I2L2k2n22222a3e3r3x33333333 4444444555"5>5S5Y6^6k6p6666666666666667 777(7-787<7O7S7f7k7x7}77777777777777888!8%84898B8F8V8\8k8o8~88888888889 99#959<9N9U9g9n99999999999:::!:6:=:R:U:j:n:::::::::::::;;R;X;h;n;{;;;;;;;;< <<(<7<<<K<O<v<|<<<<<<<<<<<<<= =>=B=Y=b=r={============ >>$>7>;>S>W>g>k>>>>>>>>>>> ????5?9?q?u????????? @@@@@@@@@@@AA,AAAAAAAAAAB!B5B`BgBBBBBBBCC'C-CJC\CCC DD-D0DODRDhDnDDDDE.E3E^EcEEERFWFdFiFxF}FFFFFFFFFFFFFGGGG!G&G1G5GHGLG_GdGqGvGGGGGGGGGGGGGGG HHHH-H2H;H?HOHUHcHgHvHyHHHHHHHHHHIII-I4IFIMI_IfIIIIIIIIIIIIIJJ.J5JJJMJbJfJxJ~JJJJJJJJJJJKKJKPK`KfKsKyKKKKKKKKLL L/L4LCLGLnLtLLLLLLLLLLLLLLM6M:MQMZMjMsMMMMMMMMMMMMNNN/N3NKNON_NcNNNNNNNNNNNOOOO-O1OiOnOOOOOOOOOPPbDbvb{bbbc+cccccGdIdedgd ee&e(eeeee!f8fSf]fff*g.g;gAggggggghh@hChbhhhhhhi i"i3i:iiiAjJjjjkkll#l)l6lmvmymmmmmnnnn`obo|o~o;p?pLpRpppqq?qEqqqqqqqrr[r`rfrjr|rrrrrrrrBsGstsxssssss6tuvcwgwtwzwwwxxxxyyPy\yyyzzTzgzhz `v"/Zm 'IXguw1MY(gs79/5oubnɧ˧5AjpzƨԨS`IMtzϪҪFHr~֫#(;OblVZgm:=Ȯܮz|9;ȰʰƱ PX\ms̴ҴuTvT7]8]B]D]P]R]U]333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333DTTTTTTTTTTTTTTTTTTTTUUUU-U-U=U=UIUIURURU]U]UmUmUUUUUUUUUUUUUUUUUUU V VVV+V+V.Fnz    _PID_HLINKS eBook-title eBook-authoreBook-filenameeBook-ThumbPatheBook-CoverPatheBook-SpinePath eBook-PPCThumbPath eBook-PPCCoverPathAZ{>Whttp://www.kalifornica.com/>P_Toc159540246>J_Toc159540245>D_Toc159540244>>_Toc159540243>8_Toc159540242>2_Toc159540241>,_Toc159540240>&_Toc159540239> _Toc159540238>_Toc159540237>_Toc159540236>_Toc159540235>_Toc159540234>_Toc159540233Main ScriptsGamemaster X NWN2 Stock Scripts (VOL I).lit@C:\Documents and Settings\Icarus\Desktop\Kalifornica Logo2.JPG  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                           ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                            ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~        !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOQRSTUVWYZ[\]^_Root Entry FPLTData T 1Table\ #WordDocumentSummaryInformation(PDocumentSummaryInformation8XCompObjj  FMicrosoft Word Document MSWordDocWord.Document.89q