Darkkender Posted August 11, 2005 Share Posted August 11, 2005 Recently I got in a discussion with another modder privately as to weather or not we can craft our own functions or not. So I decided to start crafting a custom include script for the modders of Holowan Labs. The goal is to make scripting as easy as possible for the newest members and even the old timers for our most commen scripts. Right now I have only developed one custom function for recruiting NPC's. I'm also going to post some other common scripts that we use that are encapsulated into a single function. So here is "k_inc_holowan.nss" //:://///////////////////////////////////////////// //:: Holowan Labs Include //:: k_inc_holowan //::////////////////////////////////////////////// /* This contains the functions for custom modding scripts. */ //::////////////////////////////////////////////// //:: Created By: Darkkender //:: Created On: August 4, 2005 //::////////////////////////////////////////////// #include "k_inc_debug" void RecruitNewNPC(int NPCIndex, string TemplateName); void SpawnNewNPC(float Xloc, float Yloc, float Zloc, float rotation, string TemplateName); void SpawnNewPlaceable(float Xloc, float Yloc, float Zloc, float rotation, string TemplateName); void NPCAttackTarget(string NPCTag, string TargetTag); void PCAttackTarget(string TargetTag); void RecruitNewNPC(int NPCIndex, string TemplateName) { RemoveAvailableNPC(NPCIndex); AddAvailableNPCByTemplate(NPCIndex, TemplateName); } void SpawnNewNPC(float Xloc, float Yloc, float Zloc, float rotation, string TemplateName) { vector vecNPC = Vector(Xloc,Yloc,Zloc); location locNPC = Location(vecNPC, rotation); object oNPC = CreateObject(OBJECT_TYPE_CREATURE, TemplateName, locNPC); } void SpawnNewPlaceable(float Xloc, float Yloc, float Zloc, float rotation, string TemplateName) { vector vecObj = Vector(Xloc,Yloc,Zloc); location locObj = Location(vecObj, rotation); object newObj = CreateObject(OBJECT_TYPE_PLACEABLE, TemplateName, locObj); } void NPCAttackTarget(string NPCTag, string TargetTag) { object oNPC = GetObjectByTag(NPCTag); object oTarget = GetObjectByTag(TargetTag); ChangeToStandardFaction (oTarget, STANDARD_FACTION_HOSTILE_1); DelayCommand(0.5, AssignCommand(oTarget, ActionAttack(oNPC))); } void PCAttackTarget(string TargetTag) { object oPC = GetFirstPC(); object oTarget = GetObjectByTag(TargetTag); ChangeToStandardFaction (oTarget, STANDARD_FACTION_HOSTILE_1); DelayCommand(0.5, AssignCommand(oTarget, ActionAttack(oPC))); } I'm also enclosing a sample of how this script would appear for compiling. #include "k_inc_holowan" void main() { RecruitNewNPC(3, "c3p0"); //The 3 represents the NPC party index number. //The "c3p0" is the name of the utc file without .utc. SpawnNewNPC(145.33f, 112.15f, 0.00f, 1.0f, "drkkender1"); //Spawns a NPC Darkkender at the set coordinates. //The first 3 sets of numbers are your X,Y,& Z and the 4th set is the rotation. //the "drkkender1" is the name of the utc. SpawnNewPlaceable(140.00f, 100.00f, 0.00f, 90.0f, "dk_wrkbench"); //Spawns a Placeable workbench at the set coordinates. //The first 3 sets of numbers are your X,Y,& Z and the 4th set is the rotation. //the "dk_wrkbench" is the name of the utp. void NPCAttackTarget("HK47", "Yuka_Laka"); //Directs the NPC HK47 to attack Yuka Laka. //Uses the tags for the 2 targets. void PCAttackTarget("Yuka_Laka"); //Directs the PC to attack Yuka Laka //Uses the tag for the targetted creature. } If you would like to contribute any of your own functions to this I would more than welcome them. I plan to archive this include and sample scripts in the future for others to have quick access to. For anybody out there who doubts the information above I welcome you to give our new include file and custom function a try. I also hope this becomes useful to everybody in the future and long run. Link to comment Share on other sites More sharing options...
Prime Posted August 11, 2005 Share Posted August 11, 2005 Excellent idea. Code reuse helps greatly in the long run. Do you want me to post the functions I created for my Putting the Sith Back in The Sith Lords scripts? I tried to make them as generic as possible... Link to comment Share on other sites More sharing options...
Achilles Posted August 11, 2005 Share Posted August 11, 2005 Hasn't Stoffe-mkb- been using custom include files for quite some time? If so, perhaps she can chime in with some advice. Link to comment Share on other sites More sharing options...
Darth333 Posted August 11, 2005 Share Posted August 11, 2005 I use them quite often too (the usm random loot, the lightsaber floating and the zombie force powers, per example): it can be very useful depending on what you want to do. I'd post mine but they don't really make any sense out of the usm mod...perhaps the spawning one in the force power mod could have some use... However, for the recruit thing, you could take advantage of that K2 allows you to pass parameters from a dialogue to a script. Thus, users would not need to script anything, just insert the index number and the templateResRef in the .dlg file. I think the end purpose would be better served that way IMHO Link to comment Share on other sites More sharing options...
stoffe Posted August 11, 2005 Share Posted August 11, 2005 Hasn't Stoffe-mkb- been using custom include files for quite some time? If so, perhaps she can chime in with some advice. Don't know if there is any advice to give, since functions and includes are core concepts in nwscript. Include files are useful for keeping functions that are useful in more than one script, and for grouping functions and globals for specific tasks together. If it isn't concidered off-topic and there is interest I can post my generic utility include file. It contains a bunch of functions that encapsulate a variety of common (to me anyway) scripting tasks. Link to comment Share on other sites More sharing options...
Bunk Posted August 11, 2005 Share Posted August 11, 2005 As a new modder who is still learning the scripting language (and having to dig through the .nss files of countless mods to find syntax), I can say that any includes that simplify common scripting taks would be very welcome indeed. Link to comment Share on other sites More sharing options...
Darkkender Posted August 12, 2005 Author Share Posted August 12, 2005 I use them quite often too (the usm random loot, the lightsaber floating and the zombie force powers, per example): it can be very useful depending on what you want to do. I'd post mine but they don't really make any sense out of the usm mod...perhaps the spawning one in the force power mod could have some use... However, for the recruit thing, you could take advantage of that K2 allows you to pass parameters from a dialogue to a script. Thus, users would not need to script anything, just insert the index number and the templateResRef in the .dlg file. I think the end purpose would be better served that way IMHO I was not aware of that function with K2's dialogues. @Prime, Stoffe, Darth333, & anybody else if you have custom functions includes or anything that simplifies scripting for newbies and veterans I welcome the additions. Check above and you will find some updated additions to k_inc_holowan. They include the following functions. Spawn a Creature Spawn a Placeable NPC attacks a Target PC Attacks a Target The 2 attack a target functions would be used in an a instance such as Darth333's "Kill Yuka Laka mod" for Kotor 1. Link to comment Share on other sites More sharing options...
stoffe Posted August 12, 2005 Share Posted August 12, 2005 @Prime, Stoffe, Darth333, & anybody else if you have custom functions includes or anything that simplifies scripting for newbies and veterans I welcome the additions. Very well, here is my generic utility include that contains some non-specific functions: // ======================================================================= // ST_INC_UTILS.NSS -- Generic Utility Include // ----------------------------------------------------------------------- // Generic Utility functions for accomplishing common scripting tasks. // // REMEMBER: // Only put functions here that are totally context independent and // aren't mainly suitable for a specific kind of task. Put AI-related // generic functions in "st_inc_ai" and Force-related functions in // the "st_inc_force" file. // ----------------------------------------------------------------------- // Last changed: 2005-08-02 // ======================================================================= // ======================================================================= // FUNCTION PROTOTYPES // ----------------------------------------------------------------------- // EFFECT MANIPULATION void ST_RemoveEffectByType(int nEffectType, object oTarget=OBJECT_SELF); void ST_RemoveHarmfulEffects(object oTarget=OBJECT_SELF); void ST_RemovePowerEffects(int nPower, object oTarget=OBJECT_SELF); void ST_ApplyEffectToHostile(int nDurationType, effect eEffect, object oTarget, float fDur=0.0); void ST_ApplyEffectToParty(int nDurationType, effect eEffect, float fDur=0.0); void ST_RemoveEffectTypeByCreator(object oTarget, int nEffectType, object oCreator=OBJECT_SELF); int ST_GetHasEffect(int nEffectType, object oTarget=OBJECT_SELF); // MATHS/NUMBERS STUFF string ST_IntToStringPad(int nVal, int nDigits); float ST_FMax(float fValue, float fLimit); float ST_FMin(float fValue, float fLimit); int ST_IMax(int nValue, int nLimit); int ST_IMin(int nValue, int nLimit); // CREATURE & ITEM MANIPULATION string ST_ClassToString(int nClass); void ST_HealTarget(object oTarget, int bRes=TRUE); void ST_FaceObject(object oTarget, object oSource=OBJECT_SELF); void ST_SetFacingByObject(object oTarget, object oSource=OBJECT_SELF); void ST_SetFacingByLoc(location lLoc, object oSource=OBJECT_SELF); int ST_UsesRangedWeapon(object oTarget=OBJECT_SELF); int ST_GetHasRocketLauncher(object oTarget=OBJECT_SELF); int ST_GetExpForLevel(int nLevel, object oTarget=OBJECT_SELF); int ST_GetHasItem(string sTag, object oTarget=OBJECT_SELF); int ST_GetIsInFieldOfView(object oTarget, object oSource=OBJECT_SELF, float nFOV=180.0f); // PARTY MANAGEMENT void ST_AddToPartyTable(int nSlot, string sIdent, int bUseTemplate=TRUE, int bDestroy=TRUE); void ST_SwitchMainCharacter(int nPlayer, int bRestoreParty=FALSE); int ST_GetPartySlotByTag(string sTag); // FEEDBACK void ST_Feedback(string sMessage); void ST_DebugMessage(string sText, int bTimestamp=TRUE); // ======================================================================= // FUNCTION IMPLEMENTATION // ----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // EFFECT MANIPULATION - - - - - - - - - - - - - - - - - - - - - - - - - - // ----------------------------------------------------------------------- // Returns TRUE if oTarget has an effect applied of the specified type. // Note that some effects don't have effect types and can't be found. // ----------------------------------------------------------------------- int ST_GetHasEffect(int nEffectType, object oTarget=OBJECT_SELF) { effect eEff = GetFirstEffect(oTarget); while (GetIsEffectValid(eEff)) { if (GetEffectType(eEff) == nEffectType) return TRUE; eEff = GetNextEffect(oTarget); } return FALSE; } // ----------------------------------------------------------------------- // Removes all effects of the specified type from oTarget. // ----------------------------------------------------------------------- void ST_RemoveEffectByType(int nEffectType, object oTarget=OBJECT_SELF) { effect eEff = GetFirstEffect(oTarget); while (GetIsEffectValid(eEff)) { if (GetEffectType(eEff) == nEffectType) DelayCommand(0.1, RemoveEffect(oTarget, eEff)); eEff = GetNextEffect(oTarget); } } // ----------------------------------------------------------------------- // Removes all (detectable) detrimental effects on oTarget. // ----------------------------------------------------------------------- void ST_RemoveHarmfulEffects(object oTarget=OBJECT_SELF) { effect eEff = GetFirstEffect(oTarget); int nType; while (GetIsEffectValid(eEff)) { nType = GetEffectType(eEff); if ((nType == EFFECT_TYPE_POISON) || (nType == EFFECT_TYPE_PARALYZE) || (nType == EFFECT_TYPE_STUNNED) || (nType == EFFECT_TYPE_FRIGHTENED) || (nType == EFFECT_TYPE_SLEEP) || (nType == EFFECT_TYPE_ABILITY_DECREASE) || (nType == EFFECT_TYPE_ATTACK_DECREASE) || (nType == EFFECT_TYPE_AC_DECREASE) || (nType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE) || (nType == EFFECT_TYPE_SAVING_THROW_DECREASE) || (nType == EFFECT_TYPE_DAMAGE_DECREASE) || (nType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE) || (nType == EFFECT_TYPE_FORCE_RESISTANCE_DECREASE) || (nType == EFFECT_TYPE_SKILL_DECREASE) || (nType == EFFECT_TYPE_BLINDNESS) || (nType == EFFECT_TYPE_ENTANGLE) || (nType == EFFECT_TYPE_CONFUSED) || (nType == EFFECT_TYPE_DROID_CONFUSED) || (nType == EFFECT_TYPE_DROIDSCRAMBLE) || (nType == EFFECT_TYPE_MINDTRICK)) { DelayCommand(0.1, RemoveEffect(oTarget, eEff)); } eEff = GetNextEffect(oTarget); } } // ----------------------------------------------------------------------- // Removes all effects from oTarget that originates from the specified // force power. The nPower parameter is the line number in Spells.2da // that should be looked for. // ----------------------------------------------------------------------- void ST_RemovePowerEffects(int nPower, object oTarget=OBJECT_SELF) { if (GetHasSpellEffect(nPower, oTarget)) { effect eEff = GetFirstEffect(oTarget); while (GetIsEffectValid(eEff)) { if( GetEffectSpellId(eEff) == nPower) { RemoveEffect(oTarget, eEff); } eEff = GetNextEffect(oTarget); } } } // ----------------------------------------------------------------------- // Applies an effect to the target is the target is hostile only. Use // this when applying effects with a delay to make sure the target is // still hostile. // ----------------------------------------------------------------------- void ST_ApplyEffectToHostile(int nDurationType, effect eEffect, object oTarget, float fDur=0.0) { if(GetIsObjectValid(oTarget) && !GetIsDead(oTarget) && GetIsEnemy(oTarget)) { ApplyEffectToObject(nDurationType, eEffect, oTarget, fDur); } } // ----------------------------------------------------------------------- // Applies the specified effect to all members of the active player party. // ----------------------------------------------------------------------- void ST_ApplyEffectToParty(int nDurationType, effect eEffect, float fDur=0.0) { int i; for (i = 0; i < GetPartyMemberCount(); i++) ApplyEffectToObject(nDurationType, eEffect, GetPartyMemberByIndex(i), fDur); } // ----------------------------------------------------------------------- // Remove all effects from oTarget that are of specified type and are // created by oCreator. // ----------------------------------------------------------------------- void ST_RemoveEffectTypeByCreator(object oTarget, int nEffectType, object oCreator=OBJECT_SELF) { effect eEff = GetFirstEffect(oTarget); while(GetIsEffectValid(eEff)) { if ((GetEffectCreator(eEff) == oCreator) && (GetEffectType(eEff) == nEffectType)) { RemoveEffect(oTarget, eEff); } eEff = GetNextEffect(oTarget); } } ////////////////////////////////////////////////////////////////////////// // CREATURE & ITEMS - - - - - - - - - - - - - - - - - - - - - - - - - - - // ----------------------------------------------------------------------- // Returns TRUE if oTarget has a Wrist Launcher item equipped. // ----------------------------------------------------------------------- int ST_GetHasRocketLauncher(object oTarget=OBJECT_SELF) { object oItem = GetItemInSlot( INVENTORY_SLOT_LEFTARM, oTarget ); if( GetIsObjectValid(oItem) && (GetBaseItemType(oItem) == BASE_ITEM_WRIST_LAUNCHER)) { return TRUE; } else { oItem = GetItemInSlot( INVENTORY_SLOT_RIGHTARM, oTarget ); if( GetIsObjectValid(oItem) && (GetBaseItemType(oItem) == BASE_ITEM_WRIST_LAUNCHER)) { return TRUE; } } return FALSE; } // ----------------------------------------------------------------------- // Returns TRUE if oTarget has a ranged weapon equipped. // ----------------------------------------------------------------------- int ST_UsesRangedWeapon(object oTarget=OBJECT_SELF) { object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTWEAPON, oTarget); if(GetIsObjectValid(oItem)) { switch (GetBaseItemType(oItem)) { case BASE_ITEM_BLASTER_CARBINE: case BASE_ITEM_BLASTER_PISTOL: case BASE_ITEM_BLASTER_RIFLE: case BASE_ITEM_HEAVY_BLASTER: case BASE_ITEM_HEAVY_REPEATING_BLASTER: case BASE_ITEM_REPEATING_BLASTER: case BASE_ITEM_HOLD_OUT_BLASTER: case BASE_ITEM_BOWCASTER: case BASE_ITEM_DISRUPTER_PISTOL: case BASE_ITEM_DISRUPTER_RIFLE: case BASE_ITEM_ION_BLASTER: case BASE_ITEM_ION_RIFLE: case BASE_ITEM_SONIC_PISTOL: case BASE_ITEM_SONIC_RIFLE: return TRUE; break; } } return FALSE; } // ----------------------------------------------------------------------- // Heals the targets Vitality and Force points, and removes (most) // detrimental effects from it. Unless the bRes parameter is set to FALSE // the target will be resurrected as well if they are dead. // ----------------------------------------------------------------------- void ST_HealTarget(object oTarget, int bRes=TRUE) { if (bRes) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(GetMaxHitPoints(oTarget)), oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHealForcePoints(GetMaxForcePoints(oTarget)), oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEAL), oTarget); ST_RemoveHarmfulEffects(oTarget); } // ----------------------------------------------------------------------- // Returns the amount of experience points needed by oTarget to reach // the specified character level. // ----------------------------------------------------------------------- int ST_GetExpForLevel(int nLevel, object oTarget=OBJECT_SELF) { return (nLevel * (nLevel - 1) * 500) - GetXP(oTarget); } // ----------------------------------------------------------------------- // Checks if oTarget has an item with the tag sTag in their inventory. // Set oTarget to the main character (GetFirstPC) to check if the item is // in the party inventory. // ----------------------------------------------------------------------- int ST_GetHasItem(string sTag, object oTarget=OBJECT_SELF) { return GetIsObjectValid(GetItemPossessedBy(oTarget, sTag)); } // ----------------------------------------------------------------------- // Makes oSource turn to face oTarget. // ----------------------------------------------------------------------- void ST_FaceObject(object oTarget, object oSource=OBJECT_SELF) { AssignCommand(oSource, SetFacingPoint(GetPosition(oTarget))); } // ----------------------------------------------------------------------- // Makes oSource turn to face in the same direction as oTarget. oTarget // can be any type of object with a facing, such as waypoints, placeables, // creatures... // ----------------------------------------------------------------------- void ST_SetFacingByObject(object oTarget, object oSource=OBJECT_SELF) { AssignCommand(oSource, SetFacing(GetFacing(oTarget))); } // ----------------------------------------------------------------------- // Makes oSource turn to face in the direction indicated by lLoc. // ----------------------------------------------------------------------- void ST_SetFacingByLoc(location lLoc, object oSource=OBJECT_SELF) { AssignCommand(oSource, SetFacing(GetFacingFromLocation(lLoc))); } // ----------------------------------------------------------------------- // Returns the name, as a string, of the class specified by nClass, which // is one of the CLASS_TYPE_* constants representing a row in classes.2da. // ----------------------------------------------------------------------- string ST_ClassToString(int nClass) { string sClass; switch (nClass) { case CLASS_TYPE_SOLDIER: sClass = "Soldier"; break; case CLASS_TYPE_SCOUT: sClass = "Scout"; break; case CLASS_TYPE_SCOUNDREL: sClass = "Scoundrel"; break; case CLASS_TYPE_JEDIGUARDIAN: sClass = "Jedi Guardian"; break; case CLASS_TYPE_JEDICONSULAR: sClass = "Jedi Consular"; break; case CLASS_TYPE_JEDISENTINEL: sClass = "Jedi Sentinel"; break; case CLASS_TYPE_COMBATDROID: sClass = "Combat Droid"; break; case CLASS_TYPE_EXPERTDROID: sClass = "Expert Droid"; break; case CLASS_TYPE_MINION: sClass = "Minion"; break; case CLASS_TYPE_TECHSPECIALIST: sClass = "Tech Specialist"; break; case CLASS_TYPE_BOUNTYHUNTER: sClass = "Bounty Hunter"; break; case CLASS_TYPE_JEDIWEAPONMASTER: sClass = "Jedi Weapon Master"; break; case CLASS_TYPE_JEDIMASTER: sClass = "Jedi Master"; break; case CLASS_TYPE_JEDIWATCHMAN: sClass = "Jedi Watchman"; break; case CLASS_TYPE_SITHMARAUDER: sClass = "Sith Marauder"; break; case CLASS_TYPE_SITHLORD: sClass = "Sith Lord"; break; case CLASS_TYPE_SITHASSASSIN: sClass = "Sith Assassin"; break; default: sClass = "Unknown Class"; break; } return sClass; } // ----------------------------------------------------------------------- // Returns TRUE if oTarget is in front of oSource. // ----------------------------------------------------------------------- int ST_GetIsInFieldOfView(object oTarget, object oSource=OBJECT_SELF, float nFOV=180.0f) { if (!GetIsObjectValid(oTarget) || !GetIsObjectValid(oSource)) return FALSE; if (!GetObjectSeen(oTarget, oSource)) return FALSE; vector vMPos = GetPosition(oTarget) - GetPosition(oSource); vector vOff = AngleToVector(GetFacing(oSource)); vMPos = VectorNormalize(vMPos); vOff = VectorNormalize(vOff); float fAngle = acos((vMPos.x * vOff.x) + (vMPos.y * vOff.y) + (vMPos.z * vOff.z)); return (fAngle < (nFOV / 2.0f)); } ////////////////////////////////////////////////////////////////////////// // PARTY MANAGEMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - // ----------------------------------------------------------------------- // Get the party table slot that a NPC with the specified tag usually // goes in. Only supports the tags of the standard party members. // ----------------------------------------------------------------------- int ST_GetPartySlotByTag(string sTag) { if (sTag == "atton") return NPC_ATTON; else if (sTag == "baodur") return NPC_BAO_DUR; else if (sTag == "mand") return NPC_CANDEROUS; else if (sTag == "disciple") return NPC_DISCIPLE; else if (sTag == "g0t0") return NPC_G0T0; else if (sTag == "handmaiden") return NPC_HANDMAIDEN; else if (sTag == "hanharr") return NPC_HANHARR; else if (sTag == "hk47") return NPC_HK_47; else if (sTag == "kreia") return NPC_KREIA; else if (sTag == "mira") return NPC_MIRA; else if (sTag == "t3m4") return NPC_T3_M4; else if (sTag == "visasmarr") return NPC_VISAS; return 99; } // ----------------------------------------------------------------------- // Removes the Exile from the party and turn the character in the nPlayer // party table slot into the main character. If bRestoreParty is set to // TRUE, the other party members will be put back into the party along // with the new main char. If left to False, the new main char will be // alone. // ----------------------------------------------------------------------- void ST_SwitchMainCharacter(int nPlayer, int bRestoreParty=FALSE) { int nNPC; int nParty1 = -1; int nParty2 = -1; for (nNPC = NPC_ATTON; nNPC <= NPC_DISCIPLE; nNPC++) { if (IsNPCPartyMember(nNPC)) { if (bRestoreParty && (nParty1 == -1) && (nNPC != nPlayer)) { nParty1 = nNPC; } else if (bRestoreParty && (nParty2 == -1) && (nNPC != nPlayer)) { nParty2 = nNPC; } RemoveNPCFromPartyToBase(nNPC); } } SwitchPlayerCharacter(nPlayer); if (bRestoreParty && (nParty1 != -1)) { object oNPC = SpawnAvailableNPC(nParty1, GetLocation(GetFirstPC())); AddPartyMember(nParty1, oNPC); } if (bRestoreParty && (nParty2 != -1)) { object oNPC = SpawnAvailableNPC(nParty2, GetLocation(GetFirstPC())); AddPartyMember(nParty2, oNPC); } } // ----------------------------------------------------------------------- // Add a new NPC to the party table in the specified slot. If bUseTemplate // is TRUE, sIdent is the ResRef of the NPC to add. If bUseTemplate is // false, sIdent is the Tag of a creature in the area to add. // If the specified party table slot is already occupied by another NPC, // that NPC will be removed. If the NPC is in the active party it will // be removed from the party and the area, unless bDestroy is set to // FALSE, in which case the creature will remain standing in the area // after being removed from the party. // ----------------------------------------------------------------------- void ST_AddToPartyTable(int nSlot, string sIdent, int bUseTemplate=TRUE, int bDestroy=TRUE) { if (IsNPCPartyMember(nSlot)) { if (bDestroy) RemoveNPCFromPartyToBase(nSlot); else RemovePartyMember(nSlot); } if (IsAvailableCreature(nSlot)) RemoveAvailableNPC(nSlot); if (bUseTemplate) AddAvailableNPCByTemplate(nSlot, sIdent); else AddAvailableNPCByObject(nSlot, GetNearestObjectByTag(sIdent, GetFirstPC())); if (GetPartyMemberCount() < 3) { object oNPC = SpawnAvailableNPC(nSlot, GetLocation(GetFirstPC())); AddPartyMember(nSlot, oNPC); } } ////////////////////////////////////////////////////////////////////////// // NUMBER MANIPULATION - - - - - - - - - - - - - - - - - - - - - - - - - - // ----------------------------------------------------------------------- // Returns the highest value of the two floating point values. // ----------------------------------------------------------------------- float ST_FMax(float fValue, float fLimit) { if (fValue < fLimit) fValue = fLimit; return fValue; } // ----------------------------------------------------------------------- // Returns the highest value of the two integer values. // ----------------------------------------------------------------------- int ST_IMax(int nValue, int nLimit) { if (nValue < nLimit) nValue = nLimit; return nValue; } // ----------------------------------------------------------------------- // Returns the lowest value of the two floating point values. // ----------------------------------------------------------------------- float ST_FMin(float fValue, float fLimit) { if (fValue > fLimit) fValue = fLimit; return fValue; } // ----------------------------------------------------------------------- // Returns the lowest value of the two integer values. // ----------------------------------------------------------------------- int ST_IMin(int nValue, int nLimit) { if (nValue > nLimit) nValue = nLimit; return nValue; } // ----------------------------------------------------------------------- // Return string value of the integer nVal zero-padded to the number of // digits specified by the nDigits parameter. // ----------------------------------------------------------------------- string ST_IntToStringPad(int nVal, int nDigits) { string sRes = IntToString(nVal); if (sRes != "") { int nDiff = nDigits - GetStringLength(sRes); if (nDiff > 0) { int i; for (i = 0; i < nDiff; i++) { sRes = "0" + sRes; } } } return sRes; } ////////////////////////////////////////////////////////////////////////// // FEEDBACK FUNCTIONS - - - - - - - - - - - - - - - - - - - - - - - - - - // ----------------------------------------------------------------------- // Simple wrapper to dump a text message to the Feedback screen. // ----------------------------------------------------------------------- void ST_Feedback(string sMessage) { SendMessageToPC(GetPartyLeader(), sMessage); } // ----------------------------------------------------------------------- // Writes a time-stamped debug message to the Feedback log, // indicating the name of the object that ran the function. Set the // bTimestamp parameter to FALSE to remove the timestamp. // ----------------------------------------------------------------------- void ST_DebugMessage(string sText, int bTimestamp=TRUE) { string sTimestamp = ""; if (bTimestamp) { int nHour = GetTimeHour(); int nMin = GetTimeMinute(); // ST: Ingame-time! There are 2 min/hour. int nSec = GetTimeSecond(); int nMSec = GetTimeMillisecond(); sTimestamp = (nHour < 10 ? "0" : "") + IntToString(nHour) + ":" + (nMin < 10 ? "0" : "") + IntToString(nMin) + ":" + (nSec < 10 ? "0" : "") + IntToString(nSec) + ":" + GetSubString((nMSec < 10 ? "0" : "") + IntToString(nMSec), 0, 2); sTimestamp += " - "; } SendMessageToPC(GetPartyLeader(), sTimestamp + "DEBUG[" + GetName(OBJECT_SELF) + "] " + sText); } Link to comment Share on other sites More sharing options...
rgdelta Posted August 12, 2005 Share Posted August 12, 2005 I have a request please don't combine TSL and Kotor in 1 include or mark TSL items that might crash Kotor some of us don't have TSL as much as I would like to get TSL I cannot get it yet and would love the help of this thread. Link to comment Share on other sites More sharing options...
Prime Posted August 12, 2005 Share Posted August 12, 2005 @Prime, Stoffe, Darth333, & anybody else if you have custom functions includes or anything that simplifies scripting for newbies and veterans I welcome the additions.OK. I'll dig them out tonight or tomorrow... Link to comment Share on other sites More sharing options...
Det. Bart Lasiter Posted August 13, 2005 Share Posted August 13, 2005 I'm also working on restoring functions from NWN's 'x0 i0 position' include if you'd like them. Link to comment Share on other sites More sharing options...
Darkkender Posted August 13, 2005 Author Share Posted August 13, 2005 I have a request please don't combine TSL and Kotor in 1 include or mark TSL items that might crash Kotor some of us don't have TSL as much as I would like to get TSL I cannot get it yet and would love the help of this thread. While the above recruit script is referencing a TSL NPC replacement the function is generic enough to work in either game. The same is true of the other scripts that I posted above. Really even if a function seems to reference a TSL element it likely would take very little to adjust to be generic for either one. This is one of the reasons I was posting as a scripting resource. This is because most but not all of the scripting has stayed the same between 1 & 2. The major difference comes from getting more specific purpose script functions. Link to comment Share on other sites More sharing options...
Prime Posted August 15, 2005 Share Posted August 15, 2005 Here is the config file that had my utility functions... // configuration for the NPC conversion script // Misc Settings // ------------- int feedback = FALSE; // Determines if feedback about the work of the script will be provided // to the player through the feedback screen. TRUE the script will // provide feedback, FALSE it won't. int doSaberCheck = TRUE; // Determines whether the script will check to see if the player already // has a lightsaber it their inventory. If TRUE, if the player does not // have a lightsaber the conversion will not be done. If FALSE, the // conversion will be done regardless int newNPCRatio = 1; // This specifies the ratio of old NPC type to new altered one. This // value is the modulous value to determine if the current NPC should // be changed. For example, for a value of 2, every second NPC of the // desired type will be altered. Set to 1 if every NPC is to be changed. // Appearance Settings // ------------------- int changeAppearance = TRUE; // Determines of the NPC will have it's appearance changed to the type // specified by newAppearance1 and newAppearance2. TRUE will do the // conversion, FALSE will not. int useAppearance2 = TRUE; // Indicate if newAppearance2 is to be used. TRUE it will, FALSE it // won't. Note that changeAppearance must be TRUE in order for any // appearance conversions to be done. int appearanceRatio = 7; // This specifies the ratio of how many altered NPCs should be of appearance // type 1 or 2. The higher the value, the more likely that the NPC will // be have its appearance altered to type 1. For all NPCs to be set to type 2 // set value to 1. For one of each on average, set to 2. useAppearance2 must // be TRUE for this value to be used. int sourceNPC = 528; // This specifies which NPC is to be converted. This value is the line // number of the entry in appearance.2da. int newAppearance1 = 379; // This specifies what appearance the NPC should be changed to. This value is // the line number of the entry in appearance.2da. This setting will be the // most prominant of the appearance changes int newAppearance2 = 19; // This specifies what appearance the NPC should be changed to. This value is // the line number of the entry in appearance.2da. This setting will be the // less prominant of the appearance changes. Setting useAppearance2 has to be // set to TRUE for this to be used. // Weapon Settings // --------------- int changeWeapon = TRUE; // Determines if the NPC's weapon will be changed. TRUE it will, FALSE it won't. int dualWield = FALSE; // This specifies if the NPC will dual wield it's new weapons. TRUE it will, FALSE // it won't. Note that this value needs to be true for the rangedWeapon2 // and rangedWeapon2 values to be used. int weaponType = 2; // This specifies the type of weapon the NPC's weapon will be changed to. // 0 = melee, 1 = ranged, 2 = lightsaber int saberRatio = 8; // Determines the ratio of dual and double sabers to singles. This is a random // seed value. The higher the number, the more likely the NPC will be given a // single lightsaber vs. a dual saber or double saber. For equal probabilities, // set this value to 3. string singleSaber = "g_w_lghtsbr02"; string doubleSaber = "g_w_dblsbr002"; string dualSaber = "g_w_shortsbr02"; // These determine which lightsabers to use for each lightsaber type. Note that // when the NPC dual wields, both the singleSaber (right hand) and dualSaber // (left hand) are used. string meleeWeapon = "w_melee_06"; string meleeWeapon2 = "w_melee_01"; // Determines which melee weapons are to be used when the NPC equipes new melee // weapons. In the case of dual wielding, both these values are used. string rangedWeapon = "w_brifle_04"; string rangedWeapon2 = "w_blaste_06"; // Determines which ranged weapons are to be used when the NPC equipes new ranged // weapons. In the case of dual wielding, both these values are used. // Force Settings // -------------- int grantDarkSidePowers = TRUE; // Determines if the NPC will be given Force powers. True they will, FALSE they // won't. Note that only horror and insanity seem to be used. int forceRatio = 3; // Specifies what ratio of the NPCs should have force powers. The higher the // number, the fewer force using NPCs there will be. To have every altered // NPC use Force powers, set to 1. To have half of them use powers, set to 2. // Constants // --------- // These must not be changed int SINGLESABER = 0; int DOUBLESABER = 1; int DUALSABER = 2; And the library file that the above relates to that has all the utility functions: #include "k_inc_generic" // check if the player has a lightsaber int hasLightsaber() { int hasSaber = FALSE; int itemBaseType; if(feedback) SendMessageToPC(GetFirstPC(), "hasLightsaber: Started"); // get the first inventory item object oInvItem = GetFirstItemInInventory(GetFirstPC()); while(GetIsObjectValid(oInvItem)) { itemBaseType = GetBaseItemType(oInvItem); // determine if this item is a lightsaber if((itemBaseType == BASE_ITEM_LIGHTSABER) || (itemBaseType == BASE_ITEM_DOUBLE_BLADED_LIGHTSABER) || (itemBaseType == BASE_ITEM_SHORT_LIGHTSABER)) { hasSaber = TRUE; if(feedback) SendMessageToPC(GetFirstPC(), "hasLightsaber: Lightsaber found in inventory"); break; } oInvItem = GetNextItemInInventory(GetFirstPC()); } // if a lightsaber hasn't been found in the inventory // check to see if there is one equiped if(hasSaber != TRUE) { // haven't found lightsaber yet // looping over the entire slot range isn't necessary // but it makes things a little cleaner int slot; for(slot=0; slot < NUM_INVENTORY_SLOTS; slot++) { oInvItem = GetItemInSlot(slot, GetFirstPC()); if(GetIsObjectValid(oInvItem)) { // determine if the equiped item is a lightsaber itemBaseType = GetBaseItemType(oInvItem); if((itemBaseType == BASE_ITEM_LIGHTSABER) || (itemBaseType == BASE_ITEM_DOUBLE_BLADED_LIGHTSABER) || (itemBaseType == BASE_ITEM_SHORT_LIGHTSABER)) { // found a lightsaber hasSaber = TRUE; if(feedback) SendMessageToPC(GetFirstPC(), "hasLightsaber: Lightsaber found equiped"); break; } } } } return hasSaber; } // give the NPC some dark side force powers // Note: it appears that only Horror and Insanity are used ?? void giveDSForcePowers(object oNPC) { if(feedback) SendMessageToPC(GetFirstPC(), "giveDSForcePowers: Granting force powers"); // give some force powers if(Random(forceRatio) == 0) { GrantSpell(FORCE_POWER_LIGHTNING, oNPC); GrantSpell(FORCE_POWER_DRAIN_LIFE, oNPC); GrantSpell(FORCE_POWER_FORCE_WHIRLWIND, oNPC); GrantSpell(FORCE_POWER_INSANITY, oNPC); GrantSpell(FORCE_POWER_HORROR, oNPC); GrantSpell(FORCE_POWER_FORCE_PUSH, oNPC); GrantSpell(FORCE_POWER_SHOCK, oNPC); GrantSpell(FORCE_POWER_CHOKE, oNPC); } } // give a lightsaber and required feats to the NPC void giveLightsaber(object oCreature, int saberType) { // to use a lightsaber the NPC needs some melee and lightsaber feats if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_MELEE_WEAPONS, oCreature) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_MELEE_WEAPONS, oCreature); if(GetFeatAcquired(FEAT_DOUBLE_WEAPON_FIGHTING, oCreature) == FALSE) GrantFeat(FEAT_DOUBLE_WEAPON_FIGHTING, oCreature); if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_LIGHTSABER, oCreature) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_LIGHTSABER, oCreature); if(GetFeatAcquired(FEAT_WEAPON_FOCUS_LIGHTSABER, oCreature) == FALSE) GrantFeat(FEAT_WEAPON_FOCUS_LIGHTSABER, oCreature); object oSaber, oSaber2; switch(saberType) { case 0: // single lightsaber SINGLESABER // give the NPC the lightsaber oSaber = CreateItemOnObject(singleSaber, oCreature); // have the NPC equip the lightsaber AssignCommand(oCreature, ActionEquipItem(oSaber, INVENTORY_SLOT_RIGHTWEAPON)); if(feedback) SendMessageToPC(GetFirstPC(), "giveLightsaber: single lightsaber equiped"); break; case 1: // double lightsaber DOUBLESABER // give the NPC the lightsaber oSaber = CreateItemOnObject(doubleSaber, oCreature); // have the NPC equip the lightsaber AssignCommand(oCreature, ActionEquipItem(oSaber, INVENTORY_SLOT_RIGHTWEAPON)); if(feedback) SendMessageToPC(GetFirstPC(), "giveLightsaber: double lightsaber equiped"); break; case 2: // dual lightsaber DUALSABER // give the NPC the lightsabers oSaber = CreateItemOnObject(singleSaber, oCreature); oSaber2 = CreateItemOnObject(dualSaber, oCreature); // have the NPC equip the lightsaber AssignCommand(oCreature, ActionEquipItem(oSaber, INVENTORY_SLOT_RIGHTWEAPON)); AssignCommand(oCreature, ActionEquipItem(oSaber2, INVENTORY_SLOT_LEFTWEAPON)); if(feedback) SendMessageToPC(GetFirstPC(), "giveLightsaber: dual lightsabers equiped"); break; default: break; } } // give the NPC a melee weapon void giveMeleeWeapon(object oNPC) { // give the NPC a melee weapon object oMelee = CreateItemOnObject(meleeWeapon, oNPC); // grant the required melee feats if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_MELEE_WEAPONS, oNPC) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_MELEE_WEAPONS, oNPC); if(GetFeatAcquired(FEAT_DOUBLE_WEAPON_FIGHTING, oNPC) == FALSE) GrantFeat(FEAT_DOUBLE_WEAPON_FIGHTING, oNPC); // equip the weapon AssignCommand(oNPC, ActionEquipItem(oMelee, INVENTORY_SLOT_RIGHTWEAPON)); // if using two weapons if(dualWield) { object oMelee2 = CreateItemOnObject(meleeWeapon2, oNPC); AssignCommand(oNPC, ActionEquipItem(oMelee2, INVENTORY_SLOT_LEFTWEAPON)); } } // give the NPC a ranged weapon void giveRangedWeapon(object oNPC) { // set the NPC AI to use ranged weapons if(GetNPCAIStyle(oNPC) != NPC_AISTYLE_RANGED_ATTACK) SetNPCAIStyle(oNPC, NPC_AISTYLE_RANGED_ATTACK); // grant the required ranged feats if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_BLASTER, oNPC) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_BLASTER, oNPC); if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_BLASTER_RIFLE, oNPC) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_BLASTER_RIFLE, oNPC); if(GetFeatAcquired(FEAT_WEAPON_PROFICIENCY_HEAVY_WEAPONS, oNPC) == FALSE) GrantFeat(FEAT_WEAPON_PROFICIENCY_HEAVY_WEAPONS, oNPC); if(GetFeatAcquired(FEAT_DOUBLE_WEAPON_FIGHTING, oNPC) == FALSE) GrantFeat(FEAT_DOUBLE_WEAPON_FIGHTING, oNPC); // add the weapon to the NPCs inventory object oGun = CreateItemOnObject(rangedWeapon, oNPC); // equip the weapon AssignCommand(oNPC, ActionEquipItem(oGun, INVENTORY_SLOT_RIGHTWEAPON)); // if using two weapons if(dualWield) { object oGun2 = CreateItemOnObject(rangedWeapon2, oNPC); AssignCommand(oNPC, ActionEquipItem(oGun2, INVENTORY_SLOT_LEFTWEAPON)); } } // give the NPC the desired weapon void giveWeapon(object oNPC) { // unequip right hand weapon object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTWEAPON, oNPC); if(oWeapon != OBJECT_INVALID) { if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Unequiping right weapon"); AssignCommand(oNPC, ActionUnequipItem(oWeapon)); DestroyObject(oWeapon); if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Right weapon unequiped and destroyed"); } // unequip left hand weapon oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTWEAPON, oNPC); if(oWeapon != OBJECT_INVALID) { if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Unequiping left weapon"); AssignCommand(oNPC, ActionUnequipItem(oWeapon)); DestroyObject(oWeapon); if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Left weapon unequiped and destroyed"); } // give new weapon if(weaponType == 0) // melee giveMeleeWeapon(oNPC); else if(weaponType == 1) // ranged giveRangedWeapon(oNPC); else if(weaponType == 2) // lightsaber { switch(Random(saberRatio)) { case 0: giveLightsaber(oNPC, DOUBLESABER); break; case 1: giveLightsaber(oNPC, DUALSABER); break; default: giveLightsaber(oNPC, SINGLESABER); break; } } } // change the NPC to the specified settings void changeNPC(object oNPC) { if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Started"); // give DS force powers if specified if(grantDarkSidePowers) giveDSForcePowers(oNPC); // change the appearance specified type if(changeAppearance) { if(!useAppearance2) ChangeObjectAppearance(oNPC, newAppearance1); else { int iType = Random(appearanceRatio); if(iType == 0) ChangeObjectAppearance(oNPC, newAppearance2); else ChangeObjectAppearance(oNPC, newAppearance1); } if(feedback) SendMessageToPC(GetFirstPC(), "changeNPC: Finished changing appearance"); } if(changeWeapon) giveWeapon(oNPC); } // converts some of the NPCs in the module void NPCModuleConversion() { int doConversion = TRUE; int NPCCount = 0; if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Started"); // get the first NPC object oCreature = GetFirstObjectInArea(GetArea(OBJECT_SELF), OBJECT_TYPE_CREATURE); // determine if the player has a lightsaber yet // if not, do not do the conversion if(doSaberCheck) { if(hasLightsaber()) { doConversion = TRUE; if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Player has a lightsaber"); } else { doConversion = FALSE; if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Player does not have a lightsaber"); } } // check that this NPC is valid while(GetIsObjectValid(oCreature) && doConversion) { if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: This NPC = " + GetName(oCreature)); // see if the NPC is of the desired type. if(GetAppearanceType(oCreature) == sourceNPC) { // determine of this NPC should be altered if(NPCCount % newNPCRatio == 0) { if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Calling changeNPC()"); SetLocalBoolean(oCreature, SW_FLAG_BOSS_AI, TRUE); changeNPC(oCreature); } else if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Not calling changeNPC()"); NPCCount++; } oCreature = GetNextObjectInArea(GetArea(OBJECT_SELF), OBJECT_TYPE_CREATURE); } if(feedback) SendMessageToPC(GetFirstPC(), "NPCModuleConversion: Complete"); } // converts one NPC for a spawn script void NPCConversion() { int doConversion = TRUE; if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Started"); // determine if the player has a lightsaber yet // if not, do not do the conversion if(doSaberCheck == TRUE) { if(hasLightsaber()) { doConversion = TRUE; if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Player has a lightsaber"); } else { doConversion = FALSE; if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Player does not have a lightsaber"); } } if(doConversion) { if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: This NPC = " + GetName(OBJECT_SELF)); // see if the NPC is of the desired type. if(GetAppearanceType(OBJECT_SELF) == sourceNPC) { if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Calling changeNPC()"); // change the NPC SetLocalBoolean(OBJECT_SELF, SW_FLAG_BOSS_AI, TRUE); changeNPC(OBJECT_SELF); } else if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Not calling changeNPC()"); } if(feedback) SendMessageToPC(GetFirstPC(), "NPCConversion: Complete"); } If any of that is of any use, feel free to use it and hack it apart as required... Link to comment Share on other sites More sharing options...
Darkkender Posted August 15, 2005 Author Share Posted August 15, 2005 Thank you Prime. I will be posting a updated k_inc_holowan.nss within the next few days including the various functions you, & Stoffe have posted. I'm also taking a look at Darth333's USM loot scripting include to see if it can be made more generic. I won't include those unless Darth333 gives her OK. Link to comment Share on other sites More sharing options...
kdsphantom Posted October 25, 2005 Share Posted October 25, 2005 Hiya all Sorry to bring a dead or seemingly dead thread to life, but this one sure peaked my interests when I saw it, so forgive me for that, heh I was doing a search and stumbled on this one, It was posted before I ever found the forums and started getting mods or even creating a mod. How does one get this source material and has Darth333 said okies to include her stuff yet? and then is it the #include "k_inc_holowan" then needed at the top of the script for these to work properly? and of course then holowan.ncs in your override folder? And then of course next question is the Holowan.ncs at pcgamemods (down atm but soon to be up) or did I miss it =/ at http://www.starwarsknights.com/tools.php like I have missed a few other tools much to my eternal shame? But each of you had at least one line or 1 function that I would have loved to have used in just the lil mod I made and terribly interested in getting this. thank you kdsphantom Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.