Updated Jasperre's AI
Updated Jasperre's AI to 1.4, fixed a few other coding bugs & fully compiled module.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/************************ [On Blocked] *****************************************
|
||||
Filename: j_ai_onblocked or nw_c2_defaulte
|
||||
************************* [On Blocked] *****************************************
|
||||
/*/////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Filename: J_AI_OnBlocked or nw_c2_defaulte
|
||||
///////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Added in user defined constant - won't open any doors.
|
||||
0 = Default (even if not set) opens as appropriate
|
||||
1 = Always bashes the door.
|
||||
@@ -16,14 +16,20 @@
|
||||
|
||||
Note: This also fires for blocking via. creatures. It is optimised, and
|
||||
works by re-targeting and doing a few small things to do with blocking.
|
||||
************************* [History] ********************************************
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.0 - Opens with Knock. Unlocks door. Ignores trapped doors.
|
||||
1.3 - Debug messages.
|
||||
- New events, even if the change of using them is small!
|
||||
- No ClearAllactions so any previous movings will carry on once the door is gone.
|
||||
- Removed debug messages
|
||||
1.3 - Added Creature reaction code
|
||||
************************* [Workings] *******************************************
|
||||
- Added Creature reaction code
|
||||
1.4 - Need to add a "hands" check (done on spawn, to set a setting to not
|
||||
open doors at all, IE: We do NOT have hands, do not open doors), so
|
||||
its a little more realistic "out of the box"
|
||||
- Fixed an instance of GetObjectSeen being repeated.
|
||||
- Fixed the variable AI_DOOR_INTELLIGENCE not being got via GetAIInteger().
|
||||
- Removed unneeded else statement.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Uses simple code to deal with a door in the best way possible.
|
||||
|
||||
Uses DoDoorAction, which is added to the top of an action queue and doesn't,
|
||||
@@ -31,10 +37,10 @@
|
||||
is like this)
|
||||
|
||||
Creatures are reacted by with ClearAllActions usually.
|
||||
************************* [Arguments] ******************************************
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetBlockingDoor, GetIsDoorActionPossible, GetLocked, GetLockKeyRequired
|
||||
GetLockKeyTag, GetLockUnlockDC, GetPlotFlag, DoDoorAction
|
||||
************************* [On Blocked] ****************************************/
|
||||
///////////////////////// [On Blocked] ///////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
@@ -45,10 +51,8 @@ int RangedAttack(object oTarget = OBJECT_INVALID);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-blocked-event
|
||||
if(FireUserEvent(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, EVENT_ON_BLOCKED_PRE_EVENT))
|
||||
// We may exit if it fires
|
||||
if(ExitFromUDE(EVENT_ON_BLOCKED_PRE_EVENT)) return;
|
||||
// Pre-on blocked-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, EVENT_ON_BLOCKED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
@@ -74,19 +78,20 @@ void main()
|
||||
if(GetLocalTimer(AI_TIMER_BLOCKED)) return;
|
||||
|
||||
// Set the timer for 1 second
|
||||
SetLocalTimer(AI_TIMER_BLOCKED, f1);
|
||||
SetLocalTimer(AI_TIMER_BLOCKED, 1.0);
|
||||
|
||||
// Is it an enemy?
|
||||
if(GetIsEnemy(oBlocker))
|
||||
{
|
||||
// Check if seen or heard
|
||||
if(GetObjectSeen(oBlocker) || GetObjectSeen(oBlocker))
|
||||
if(GetObjectSeen(oBlocker) || GetObjectHeard(oBlocker))
|
||||
{
|
||||
// Enemy :-) We can re-target (as know of thier presence), using
|
||||
// them as a target.
|
||||
// - This overrides even casting a spell - basically, as we should
|
||||
// be moving, this will re-cast it at someone or something in range
|
||||
SetAIObject(AI_ATTACK_SPECIFIC_OBJECT, oBlocker);
|
||||
|
||||
// Check if we can do combat - if we cannot, we can re-do combat
|
||||
// next time
|
||||
if(!GetIsBusyWithAction())
|
||||
@@ -106,6 +111,9 @@ void main()
|
||||
{
|
||||
SetAIObject(AI_LAST_TO_GO_INVISIBLE, oBlocker);
|
||||
}
|
||||
// Shout to allies
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// Check if we can do combat
|
||||
if(!GetIsBusyWithAction())
|
||||
{
|
||||
@@ -125,42 +133,62 @@ void main()
|
||||
|
||||
// Were we attacking in combat?
|
||||
object oPrevious = GetAttackTarget();
|
||||
|
||||
// Check action
|
||||
if(GetCurrentAction() == ACTION_ATTACKOBJECT)
|
||||
{
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(I_WAS_ATTACKED);
|
||||
// This gets set to FALSE if we can cutthrough attack,
|
||||
// or whatever.
|
||||
|
||||
int bPreviousAttackFailed = FALSE;
|
||||
// Check if we can see our previous target
|
||||
if(GetObjectSeen(oPrevious) ||
|
||||
(GetObjectHeard(oPrevious) && LineOfSightObject(OBJECT_SELF, oPrevious)))
|
||||
{
|
||||
// We can! see if we can re-attack with ranged weapon, else
|
||||
// doesn't matter we can see them
|
||||
if(RangedAttack(oPrevious)) return;
|
||||
bPreviousAttackFailed = RangedAttack(oPrevious);
|
||||
}
|
||||
else
|
||||
// We have not stopped the script - so determine combat
|
||||
// round against nearest seen or heard enemy!
|
||||
if(RangedAttack()) return;
|
||||
// Else normal round to try and get a new target
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
|
||||
// If we havn't added an action yet...
|
||||
if(bPreviousAttackFailed == FALSE)
|
||||
{
|
||||
// We have not stopped the script - so determine combat
|
||||
// round against nearest seen or heard enemy!
|
||||
if(!RangedAttack())
|
||||
{
|
||||
// Else normal round to try and get a new target
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else // if(iAction == ACTION_CASTSPELL and others)
|
||||
else // if(nAction == ACTION_CASTSPELL and others)
|
||||
{
|
||||
// Reinitate combat
|
||||
// Reinitate combat, but don't attack oPrevious
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Placeable - Not sure it can be returned, however, we can add it to the
|
||||
// type if/else check.
|
||||
// Placeable - Currently not returned, however, added just in case!
|
||||
else if(nBlockerType == OBJECT_TYPE_PLACEABLE)
|
||||
{
|
||||
// Check for plot, and therefore attack it to bring it down.
|
||||
@@ -171,26 +199,29 @@ void main()
|
||||
{
|
||||
// Do placeable action
|
||||
DoPlaceableObjectAction(oBlocker, PLACEABLE_ACTION_BASH);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Door behaviour
|
||||
else if(nBlockerType == OBJECT_TYPE_DOOR)
|
||||
{
|
||||
int iDoorIntelligence = GetLocalInt(OBJECT_SELF, AI_DOOR_INTELLIGENCE);
|
||||
int iInt = GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE);
|
||||
if(iDoorIntelligence == i1)// 1 = Always bashes the doors, plot, locked or anything.
|
||||
int nDoorIntelligence = GetAIInteger(AI_DOOR_INTELLIGENCE);
|
||||
int nInt = GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE);
|
||||
if(nDoorIntelligence == 1)// 1 = Always bashes the doors, plot, locked or anything.
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
// We re-initiate combat.
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(iDoorIntelligence == i2)// 2 = Never open anything, bashing or not.
|
||||
else if(nDoorIntelligence == 2)// 2 = Never open anything, bashing or not.
|
||||
{
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(iDoorIntelligence == i3)// 3 = Never tries anything against plot doors.
|
||||
else if(nDoorIntelligence == 3)// 3 = Never tries anything against plot doors.
|
||||
{
|
||||
if(GetPlotFlag(oBlocker))
|
||||
{
|
||||
@@ -198,10 +229,10 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(iInt >= i5)
|
||||
if(nInt >= 5)
|
||||
{
|
||||
// Need some intelligence :-)
|
||||
if(iInt >= i7)
|
||||
if(nInt >= 7)
|
||||
{
|
||||
// Right, first, we may...shock...open it!!!
|
||||
// Checks Key, lock, trap and if the action is possible.
|
||||
@@ -221,17 +252,17 @@ void main()
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER) &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSkill(SKILL_OPEN_LOCK) &&
|
||||
GetIsDoorActionPossible(oBlocker, DOOR_ACTION_UNLOCK) && !GetIsTrapped(oBlocker) &&
|
||||
(GetSkillRank(SKILL_OPEN_LOCK) >= (GetLockLockDC(oBlocker) - i20)))
|
||||
(GetSkillRank(SKILL_OPEN_LOCK) >= (GetLockLockDC(oBlocker) - 20)))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_UNLOCK);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
// Specilist thing - knock
|
||||
if(iInt >= i10)
|
||||
if(nInt >= 10)
|
||||
{
|
||||
if((GetIsDoorActionPossible(oBlocker, DOOR_ACTION_KNOCK)) &&
|
||||
GetLockUnlockDC(oBlocker) <= i25 &&
|
||||
GetLockUnlockDC(oBlocker) <= 25 &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSpell(SPELL_KNOCK))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_KNOCK);
|
||||
@@ -239,16 +270,16 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If Our Int is over 5, we will bash after everything else.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_BASH) && !GetPlotFlag(oBlocker))
|
||||
}
|
||||
// If Our Int is over 5, we will bash after everything else.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_BASH) && !GetPlotFlag(oBlocker))
|
||||
{
|
||||
if(GetAttackTarget() != oBlocker)
|
||||
{
|
||||
if(GetAttackTarget() != oBlocker)
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
}
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
}
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,11 +315,13 @@ int RangedAttack(object oTarget)
|
||||
// Ranged weapon attack against oTarget
|
||||
// doesn't matter we can see them
|
||||
object oRanged = GetAIObject(AI_WEAPON_RANGED);
|
||||
int iAmmo = GetAIInteger(AI_WEAPON_RANGED_AMMOSLOT);
|
||||
int nAmmo = GetAIInteger(AI_WEAPON_RANGED_AMMOSLOT);
|
||||
|
||||
// Check ammo and validness
|
||||
if(GetIsObjectValid(oRanged) && (iAmmo == INVENTORY_SLOT_RIGHTHAND ||
|
||||
GetIsObjectValid(GetItemInSlot(iAmmo))))
|
||||
if(GetIsObjectValid(oRanged) && (nAmmo == INVENTORY_SLOT_RIGHTHAND ||
|
||||
GetIsObjectValid(GetItemInSlot(nAmmo))))
|
||||
{
|
||||
// Attack with it
|
||||
ClearAllActions();
|
||||
ActionEquipItem(oRanged, INVENTORY_SLOT_RIGHTHAND);
|
||||
ActionAttack(oRangedTarget);
|
||||
|
Reference in New Issue
Block a user