OP
addict
Joined: Sep 2015
|
First, thanks for testing the script! The second case can be solved, the first one might remain as a situation that a character can't handle properly (i. e. he'd need some turns) or at all (mostly when other characters block the path; but, at least, those characters closest to the blocking items would be able to solve the situation immediately or after a few attempts; some unnecessary behaviour might be solved by a new event we add, s. below). 2) Second first: it happens due to item weight: Chests have 50,000 weight, so I have to increase the limit. This would also include Straw, Anvil B and Grain Sack, but unfortunately also a few unmovable objects. For special barrels (ooze, oil, water) we'd need 60,000 which isn't a problem since there don't seem to be other objects between 50,000 and 60,000 and no other items with 60,000. Do you think it would be okay to increase the weight of some unmovable 50,000 items to 61,000 to exclude them?* This would be: GEN_HeavyMetal (probably; do you know what items this is for?) Gen_Door_Weak (though doesn't seem to be used often, only found one in Cyseal, a tutorial door) Gen_Stone_Indestructible Gen_HeavyMetalLightSource (maybe, don't know which items have this stat) Gen_SpawnHole_Weak (though probably irrelevant) Gen_SpawnHole_Strong (same) _TrapObjects To leave them included wouldn't be too much of a problem but require more attempts to solve the situation. *or decrease the weight of relevant 50,000 and 60,000 weight items to 40,000. 1) Yeah, big characters are quite limited in some situations. They often don't have an alternative path and often can't reach the temporary target either (due to blocking characters and other objects), so they move the wrong items, which are closer to them. Though smaller characters should be able to solve the situation after a while. With 'instead of taking actions' you mean there would have been a possible target to attack but they had chosen another, unreachable one? It's hard to judge without knowing the exact circumstances, but they must have chosen an unreachable target by default (not my script) or the GetClose and MoveItems reactions where still active from their previous turns, so they didn't return to their default behaviour as long as they didn't reach the temporary target and the target where their movement initially failed. For this case - and other unintended behaviour related to unnecessarily active GetClose/MoveItems reactions - there should this event be added to the 'ABRAX_PathBlockAI' script, to make sure that they always try to execute default behaviour first on their turn and never execute actions that aren't necessary any more:
EVENT SetPathAIPriorities
ON
OnTurnEnded() //also thrown when __Me kills the last enemy to end combat
ACTIONS
SetPriority("GetClose",0)
SetPriority("MoveItems",0)
Whole script:
INIT
CHARACTER:__Me
EXTERN FLOAT3:%TargetPos = null
FLOAT3:%TempTarget
INT:%ItemMoveSuccess = 0
/* //to be added to every reaction with movement
VARS
FLOAT3:_Pos
INTERRUPT
Reset()
ON
OnMovementFailed(_Pos)
ACTIONS
SetVar(__Me,"TargetPos",_Pos)
CharacterEvent(__Me,"ActivateGetClose")
*/
BEHAVIOUR
REACTION GetClose, 0
USAGE PEACE
USAGE COMBAT
VARS
FLOAT:_distance
FLOAT:_MyX
FLOAT:_MyZ
FLOAT:_TargetX
FLOAT:_TargetZ
FLOAT:_AttemptCounter = 0
FLOAT:_AddX
FLOAT:_AddZ
FLOAT:_Divisor
FLOAT3:_Target
FLOAT3:_MyPos
FLOAT3:_TargetPosition
ACTIONS
IF "c1&c2"
GetPosition(__Me,_MyPos)
GetVar(_TargetPosition,__Me,"TargetPos")
THEN
Set(%TempTarget,_TargetPosition)
ENDIF
IF "c1&c2&c3&c4&c5"
GetX(_MyPos,_MyX)
GetZ(_MyPos,_MyZ)
GetX(_TargetPosition,_TargetX)
GetZ(_TargetPosition,_TargetZ)
GetDistance(_distance,__Me,_TargetPosition)
THEN
Subtract(_TargetX,_MyX)
Subtract(_TargetZ,_MyZ)
GetRandom(_Divisor,1.8,1.9,2,2.1,2.2)
Divide(_TargetX,_Divisor)
Divide(_TargetZ,_Divisor)
Add(_MyX,_TargetX)
Add(_MyZ,_TargetZ)
SetX(%TempTarget,_MyX)
SetZ(%TempTarget,_MyZ)
CharacterLookAt(%TempTarget)
IF "c1"
IsGreaterThen(_AttemptCounter,4)
THEN
Set(_AttemptCounter,0)
SetPriority("MoveItems",0)
IF "c1"
IsInCombat(__Me)
THEN
CharacterEndTurn()
ELSE
DelayReaction("GetClose",5)
ENDIF
SetPriority("GetClose",0)
ELIF "c1"
IsLessThen(_distance,4)
THEN
CharacterLookAt(_TargetPosition)
IF "c1"
IsInCombat(__Me)
THEN
CharacterMoveTo(_TargetPosition,1,0,0,0.2,1)
ELSE
CharacterMoveTo(_TargetPosition,0,0,0,0.2,1)
ENDIF
SetPriority("GetClose",0)
ELIF "!c1"
IsLessThen(_distance,4)
THEN
IF "!c1"
FindValidPosition(%TempTarget,4,__Me)
THEN
Interrupt("GetClose")
ENDIF
IF "c1"
IsInCombat(__Me)
THEN
CharacterMoveTo(%TempTarget,1,0,0,0.2,1.4)
ELSE
CharacterMoveTo(%TempTarget,0,0,0,0.2,1.4)
ENDIF
SetPriority("MoveItems",0)
ELSE
Set(_AttemptCounter,0)
SetPriority("MoveItems",0)
SetPriority("GetClose",0)
ENDIF
ENDIF
INTERRUPT
Reset()
ON
OnMovementFailed(_)
OnManualInterrupt("GetClose")
ACTIONS
Add(_AttemptCounter,1)
SetPriority("MoveItems",3000)
SetPriority("GetClose",0)
REACTION MoveItems, 0
USAGE PEACE
USAGE COMBAT
VARS
ITEM:_Item
ITEM:_Item2
ITEM:_IgnoreItem1
ITEM:_IgnoreItem2
ITEM:_IgnoreItem3
FLOAT:_Weight
FLOAT:_X
FLOAT:_Z
FLOAT:_MyPosX
FLOAT:_MyPosZ
FLOAT3:_MyPos
CHARACTER:_Enemy
CHECK "(((((c1&c2)|(c3&c4))&c5&c6&((!c7&c8)|c9))|(c10&c11&c12&((!c13&c14)|c15)))&!c16)|(c17&c18)"
IsRandom(0.4)
ItemGet(_Item,__Me,6,Lowest,Distance,"")
ItemGet(_Item,__Me,6,Random,Distance,"")
CanSee(__Me,_Item)
IsFacing(__Me,_Item)
ItemGetStat(_Weight,_Item,Weight)
IsLessThen(_Weight,1000)
IsLessThen(_Weight,60001)
IsEqual(_Weight,200000) //Ice_Crystal
ItemGet(_Item,%TempTarget,6,Random,Distance,"")
IsFacing(__Me,_Item)
ItemGetStat(_Weight,_Item,Weight)
IsLessThen(_Weight,1000)
IsLessThen(_Weight,60001)
IsEqual(_Weight,200000) //Ice_Crystal
ItemIsDestroyed(_Item)
IsInCombat(__Me)
CharacterGet(_Enemy,__Me,5,Lowest,Distance,Enemy)
ACTIONS
IF "!c1"
IsEqual(_Enemy,null)
THEN
CharacterMoveTo(_Enemy,1)
CharacterAttack(_Enemy)
Goto("End")
ENDIF
IF "c1"
IsInCombat(__Me)
THEN
CharacterMoveTo(_Item,1)
ELSE
CharacterMoveTo(_Item)
ENDIF
IF "c1"
IsEqual(_Weight,200000) //Ice_Crystal
THEN
WHILE "!c1"
ItemIsDestroyed(_Item)
DO
CharacterAttack(_Item)
ENDWHILE
ELSE
GetPosition(__Me,_MyPos)
GetRandom(_X,-3,-2,2,3)
GetRandom(_Z,-3,-2,2,3)
IF "!c1&c2&c3"
ItemIsDestroyed(_Item)
GetX(_MyPos,_MyPosX)
GetZ(_MyPos,_MyPosZ)
THEN
Subtract(_MyPosX,_X)
Subtract(_MyPosZ,_Z)
SetX(_MyPos,_MyPosX)
SetZ(_MyPos,_MyPosZ)
IF "c1"
FindValidPosition(_MyPos,6,_Item)
THEN
StartTimer("CheckMoveItemSuccess",3,0)
CharacterMoveItem(_Item,_MyPos)
Set(%ItemMoveSuccess,1)
ENDIF
ENDIF
ENDIF
Label("End")
Set(_Enemy,null)
SetPriority("MoveItems",0)
INTERRUPT
Reset()
Set(_Enemy,null)
SetPriority("MoveItems",0)
EVENTS
EVENT CheckItemMoveSuccess
ON
OnTimer("CheckMoveItemSuccess")
ACTIONS
IF "c1"
IsEqual(%ItemMoveSuccess,1)
THEN
Set(%ItemMoveSuccess,0)
ELSE
Interrupt("MoveItems")
ENDIF
EVENT GetCloseActivation
ON
OnCharacterEvent(__Me,"ActivateGetClose")
ACTIONS
SetPriority("GetClose",2000)
EVENT SetPathAIPriorities
ON
OnTurnEnded() //also thrown when __Me kills the last enemy to end combat
ACTIONS
SetPriority("GetClose",0)
SetPriority("MoveItems",0)
Edit: Also looking through the object stats to improve the item selection. Seems a lot of small items (paintings, weapons etc.) can be excluded without much effort.
Last edited by Abraxas*; 24/02/17 10:43 PM.
|