Dak Vesser Posted September 21, 2005 Share Posted September 21, 2005 These are some really good AI templates that you can use for your mods. I'll post new AI templates at the top of this thread. **************************************************************************** NewTemplate posted 10/01/05 Adding timestamps in your henchmen's debug messages This is just a simple userdefined script I created that causes the henchmen to post a timestamped message everytime it spots a friend. #include "k_inc_debug" /* In order to use this script the right way, you'll need to: 1. Go into "k_hen_spawn01" and uncomment GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION); and then re-save & compile it as a new script for your creature's "OnSpawn" 2. Then attach this script, compile it and drop it in your creature's "OnUserDefined" */ void main() { int nUser = GetUserDefinedEventNumber(); if(nUser == 1002) { object oPc = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND); { //*********************************** Creating the Clock ************************************** /* From here let's create a clock so we can have timestamps in our debug messages. This formula will give us a military format: "0h:00m" to "23h:59m" It's important to know that SWKotOR/SWkoTORII time is allot faster than Real Time. This is because the developers configured the "Minutes/Hours" setting to 2 in the every Module. That means it only takes two Real Time minutes to reach one kotOR hour. So we'll use this formula to convert the 2 RT minutes into 60 KotOR minutes which will still be at the speed of 2 minutes but at least you'll see a 0-59 ratio. We could call it "RST" Republic Standard Time. This is my modified version of Skanzo Sylan's "Time Display" script for Neverwinter Nights, that I fit to work in a SWKotOR Henchmen script. */ string sTime; string sMinute; int nMinByHour = FloatToInt(HoursToSeconds(1)) / 60; int nHour = GetTimeHour(); int nMinute = (60 / nMinByHour) * GetTimeMinute(); int nSecond = GetTimeSecond(); nMinute = nMinute + nSecond / nMinByHour; if(nMinute <= 9) sMinute = "0" + IntToString(nMinute); if(nMinute >= 10) sMinute = IntToString(nMinute); sTime = "SWTime: " + IntToString(nHour) + "h:" + sMinute + "m "; //******************************** Time Stamping the Message ********************************** // When our henchmen spots a friend or anyone in the same faction, it'll post // a simple "hello" message on the feedback screen with a timestamp. if(GetLastPerceptionSeen()) { if(GetIsFriend(GetLastPerceived())) { ActionDoCommand(SetFacingPoint(GetPosition(oPc)); ActionPlayAnimation(ANIMATION_FIREFORGET_GREETING); SendMessageToPC(GetFirstPC(), sTime +"Debug Message: " +GetName(OBJECT_SELF)+ " just said hello to "+GetName(oPc)+"."); } } } } } ************************************************************************ "The Fake Party Member" This is a custom heartbeat script I created for non party creatures that will follow you around within a module. // k_fpm_heartbtxx #include "k_inc_debug" #include "k_inc_generic" #include "k_inc_switch" #include "k_inc_utility" void main() { object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode()) { if(GetPartyMemberByIndex(0) != OBJECT_SELF) { if(//GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW && GetCurrentAction(OBJECT_SELF) != ACTION_WAIT && !GetIsConversationActive() && !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) && GetCommandable()) { if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy)) ClearAllActions(); if(GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) < 5.0) { ClearAllActions(); ActionForceMoveToObject(GetPartyMemberByIndex(0), FALSE, 1.0); //SendMessageToPC(GetFirstPC(), "Debug Message: Henchmen just executed the bWalk routine."); } if(GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 5.0) { ClearAllActions(); ActionForceMoveToObject(GetPartyMemberByIndex(0), TRUE, 3.5); //SendMessageToPC(GetFirstPC(), "Debug Message: Henchmen just executed the bRun routine."); } } } } else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER) { ClearAllActions(); } if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT)) { SignalEvent(OBJECT_SELF, EventUserDefined(1001)); } } This next one I created is an On Blocked Script. Added "Picked Lock Routine" for the Holo Droid just in case a locked door gets in its Pathway, it can unlock or attempt to unlock and open it. That way, the player won't have to Deactivate/reactivate the droid to get it back to within float range. The reason for this is because when I added the “PC Location Jump” options in the planetary Debug section of the "g_cheatbot01" dialogue, I needed to make sure the Holo Droid could follow and or catch up. #include "k_inc_debug" #include "k_inc_generic" #include "k_inc_switch" #include "k_inc_utility" void main() { object oDoor = GetBlockingDoor(); if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) { if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5) { if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7 ) { DoDoorAction(oDoor, DOOR_ACTION_OPEN); SendMessageToPC(GetFirstPC(), "Debug Message: Henchmen just executed the -door open- routine..."); } if(GetLocked(oDoor)) { DoDoorAction(oDoor, DOOR_ACTION_UNLOCK); SendMessageToPC(GetFirstPC(), "Debug Message: Henchmen just executed the -picked lock- routine..."); } else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH)) { DoDoorAction(oDoor, DOOR_ACTION_BASH); SendMessageToPC(GetFirstPC(), "Debug Message: Henchmen just executed the -door bash- routine..."); } } } if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED)) { SignalEvent(OBJECT_SELF, EventUserDefined(1009)); } } This is a good script if you wanna create a creature with a custom pathway through a locked door.. ======================================================================================= Here’s a really cool Heartbeat script, I just created. I call it “The Shape Shifter”. Basically it makes the Henchmen do a random appearance change using the RollDice method equaling to d10(1). I also added a fire effect for every time it changes. I created two versions, one for the “Fake Party Member”, and the other, for the “Real Party Member”. This first Script switches from 10 different droids, and the second script switches from 10 different organics. But of course you can change'em to what ever you want.. For the “Fake Party Member” or the creature that’s going to follow the one in lead; #include "k_inc_debug" #include "k_inc_generic" #include "k_inc_switch" #include "k_inc_utility" int iRollDice = d10(1); //From 1-10, what number will the dice land on? Well, It's up to the game engine now. void main() { effect eBlind = EffectVisualEffect(VFX_PRO_DRAIN); object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode()) { if(GetPartyMemberByIndex(0) != OBJECT_SELF) { if(//GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW && GetCurrentAction(OBJECT_SELF) != ACTION_WAIT && !GetIsConversationActive() && !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) && GetCommandable()) { if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy)) ClearAllActions(); if(GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) < 5.0) { ClearAllActions(); ActionForceMoveToObject(GetPartyMemberByIndex(0), FALSE, 1.5); //SendMessageToPC(GetFirstPC(), "Debug Message: -Holo- Droid just executed the bRun routine."); } if(GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 5.0) { ClearAllActions(); ActionForceMoveToObject(GetPartyMemberByIndex(0), TRUE, 3.5); //SendMessageToPC(GetFirstPC(), "Debug Message: -Holo- Droid just executed the bWalk routine."); } if(d100(1) > 51) //50% Chance of a random switch, meaning how fast. { switch(iRollDice) //Generated Number { case 1: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 64)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 1 is now Active: Droid_Sentry transformation."); break; case 2: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 57)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 2 is now Active: Droid_Astro_01 transformation."); break; case 3: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 59)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 3 is now Active: Droid_Mark_Four transformation."); break; case 4: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 60)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 4 is now Active: Droid_Mark_One transformation."); break; case 5: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 65)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 5 is now Active: Droid_Spyder transformation."); break; case 6: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 61)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 6 is now Active: Droid_Mark_Two transformation."); break; case 7: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 538 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 7 is now Active: Droid_NPC_hk50 transformation."); break; case 8: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 581)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 8 is now Active: Droid_Mining_Mark_Two_B transformation."); break; case 9: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 630)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 9 is now Active: Droid_MineFloating transformation."); break; case 10: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 555)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 10 is now Active: Droid_Construction_Medium transformation."); break; } } } } } else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER) { ClearAllActions(); } if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))//Close this gap so it reads _HEARTBEAT!!! { SignalEvent(OBJECT_SELF, EventUserDefined(1001)); } } For the “Real Party Member” or the creature that’s going to be added to the Party table; #include "k_inc_debug" #include "k_inc_generic" #include "k_inc_switch" #include "k_inc_utility" int iRollDice = d10(1); //From 1-10, what number will the dice land on? Well, It's up to the game engine now. void main() { effect eFire = EffectVisualEffect(VFX_PRO_DRAIN);//Gives a Fire Glow effect on switching. object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode()) { if(GetPartyMemberByIndex(0) != OBJECT_SELF) { if(IsObjectPartyMember(OBJECT_SELF) && //GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW && GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT && //GetCurrentAction(OBJECT_SELF) != ACTION_WAIT && GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOWLEADER && !GetIsConversationActive() && //GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 4.5 && !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) && GetCommandable()) { if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy)) { ClearAllActions(); ActionFollowLeader(); if(d100(1) > 41) //60% Chance of a random switch, meaning how fast. { switch(iRollDice) //Generated Number { case 1: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 653 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 1 is now Active: Twilek_Assasin_02 transformation."); break; case 2: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 22 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 2 is now Active: Unique_Darth_Revan transformation."); break; case 3: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 52 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 3 is now Active: Unique_Vandar transformation."); break; case 4: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 79 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 4 is now Active: Creature_Rakghoul transformation."); break; case 5: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 249 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 5 is now Active: Creature_Kath_Hound_B03 transformation."); break; case 6: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 274 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 6 is now Active: Alien_Wookie_Male_05 transformation."); break; case 7: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 457 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 7 is now Active: Party_NPC_Visas transformation."); break; case 8: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 491 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 8 is now Active: Unique_Darth_Traya transformation."); break; case 9: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 458 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 9 is now Active: Unique_Darth_Sion transformation."); break; case 10: ClearAllActions(); ActionDoCommand(ChangeObjectAppearance(OBJECT_SELF, 553 )); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFire, OBJECT_SELF, 1.0f); //SendMessageToPC(GetFirstPC(), "Henchmen's Case 10 is now Active: Creature_Laigrek_01 transformation."); break; } } } } } } else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER) { ClearAllActions(); } if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))// Close this gap so it reads as HEARTBEAT!!! { SignalEvent(OBJECT_SELF, EventUserDefined(1001)); } } Note: When you have two routines on top of one another in an AI script, such as: void ActionForceMoveToObject; to Move to the Object, and void Switch(iRollDice) to start the random Case switching, The Henchmen can only call for ONE Routine at a time - meaning, It can't move to the oObject and Switch appearances at the same time.. So If it is infact switching appearances then It won't move until a ClearAllActions() is called, or if the party leader moved into float range of the void ActionForceMoveToObject routine. Also, The Odds of a Party Member Shape shifting is a little bit higher than the Non Party Script and that's because it's calling for the Void ActionFollowLeader(); Routine more often and ignores the Switching. But when it is Switching, then it's ignoring the Void ActionFollowLeader();.. Well, Hope you guys like these. These scripts are using SWkoTOR II TSL Appearances. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.