home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 56 / CDPowerplay56Disc2.iso / demos / blade / data1.cab / Program_Executable_Files / Lib / Enm_Def.py < prev    next >
Encoding:
Text File  |  2000-10-27  |  64.9 KB  |  2,010 lines

  1. import Bladex
  2. import whrandom
  3. import AuxTran
  4. import ScorerActions
  5. import Actions
  6. import Reference
  7. import Basic_Funcs
  8. import Combat
  9. import CharStats
  10. import copy
  11. import whrandom
  12. #import BDAux
  13. import Damage
  14. import Stars
  15. import DMusic
  16. import GameStateAux
  17. #if Reference.DEBUG_INFO == 1:
  18. import pdb    
  19.  
  20. DEBUG_SOUNDS=0
  21. ##################################################################################
  22. #  E V E N T S
  23.  
  24.     # We see the enemy ["SeeFunc"]
  25.     # 
  26.     # We have lost the enemy ["DelayNoSeenFunc"]
  27.     # We have entered an illegal area ["NoAllowedAreaFunc"]
  28.     # Our enemy (who we are chasing) enters an illegal area) ["EnemyNoAllowedAreaFunc"]
  29.     # We are hurt ["ImHurtFunc"]
  30.     # We die ["ImDeadFunc"]
  31.     # Our enemy dies ["EnemyDeadFunc"]
  32.     # An animation ends ["AnmEndedFunc"]
  33.     # We enter close weapon range with our enemy ["EnterCloseFunc"]
  34.     # We enter far weapon range (bows/crossbows) ["EnterLargeFunc"]
  35.     # We enter our primary action area  ["EnterPrimaryAAFunc"]
  36.     # We enter our secondary action area["EnterSecondaryAAFunc"]
  37.     # Another character entity sees his enemy ["CharSeeingEnemyFunc"]
  38.     # Executed a combo for the first time ["NewComboFunc"]
  39.     # Engage/disengage combat mode ["ToggleCombatFunc"]
  40.  
  41. ##################################################################################
  42. #
  43. #
  44. # Pseudo defines
  45. #
  46. #
  47. ##################################################################################
  48.  
  49. #
  50. # Twinkle FX for several kinds of objects
  51. #
  52. TwinkleObjs = ["Gema"]
  53.  
  54. THROWNHURTTIME_GAP=45
  55. #
  56. #Several sets of values needed for the SetAnmFlags() and SetTmpAnmFlags() methods
  57. #
  58.  
  59. #"bng_mov" parameter
  60. BM_IDC=0
  61. BM_NONE=1
  62. BM_XYZ=2
  63. BM_XZ=3
  64. BM_2ANM=4
  65. BM_SCRIPT=5
  66.  
  67. #"headf" parameter
  68. HEADF_ENG=0
  69. HEADF_ANM=1
  70. HEADF_ANM2SEE=2
  71. HEADF_ANM2ENG=3
  72.  
  73.  
  74.  
  75. #
  76. #Values returned by AstarState
  77. #
  78. ASTAR_THINKING=0
  79. ASTAR_NOSOLVED=1
  80. ASTAR_SOLVED=2
  81. ASTAR_RECALCULATING=3
  82.  
  83. #
  84. # Boolean value
  85. #
  86. TRUE = 1==1
  87. FALSE = not TRUE
  88.  
  89.  
  90. #
  91. #NOTE :Values returned by StatR() AND StatL() are declared in Actions.py
  92. #
  93.     
  94.  
  95. #
  96. #Values returned by the Wuea("WaitUntilEnfofAnimation")
  97. #
  98. WUEA_NONE=0    #It does not have to wait (relax , jog or similars)
  99. WUEA_WAIT=1    #It has to wait , and is waiting to end it
  100. WUEA_ENDED=2   #It has to wait , and it has just ended
  101.  
  102. #
  103. #Values returned by GetActionMode() 
  104. #
  105. ROUTE_WATCH=0  #Watch mode
  106. ROUTE_BAY=1    #Performing a bay route
  107. ROUTE_CHASE=2  #Chase a character
  108. ROUTE_SINGLE=3 #Following a single route (going to just a point)
  109. ROUTE_BOWING=4 #Bowing (OR trying to bow) an enemy
  110. ##################################################################################
  111.  
  112. # Comparison results for sorting
  113. CHOOSE_FIRST  = -1
  114. CHOOSE_SECOND =  1
  115. CHOOSE_EITHER =  0
  116.  
  117. # yeah! cool sounds 
  118. new_key_sound = Bladex.CreateSound('..\\..\\Sounds\\Manipulado-llave2.wav', 'NewKeySound')
  119. new_key_sound.Volume=1
  120. new_key_sound.MinDistance=10000
  121. new_key_sound.MaxDistance=20000
  122.  
  123. ##################################################################################
  124. #
  125. #
  126. # Sorting enemy functions
  127. #
  128. #
  129. ##################################################################################
  130.  
  131. def ChooseNearest (entity1name, entity2name):
  132.     p1 = Bladex.GetEntity(entity1name)
  133.     p2 = Bladex.GetEntity(entity2name)
  134.     if not p1 and not p2:
  135.         return CHOOSE_EITHER
  136.     elif not p1:
  137.         return CHOOSE_SECOND
  138.     elif not p2:
  139.         return CHOOSE_FIRST
  140.  
  141.     if p1.Life <= 0 and p2.Life <= 0:
  142.         return CHOOSE_EITHER
  143.     elif p1.Life <= 0:
  144.         return CHOOSE_SECOND
  145.     elif p2.Life <= 0:
  146.         return CHOOSE_FIRST
  147.  
  148.  
  149.     # If it just comes down to distance, group leaders may order others before them
  150.     if p1.Data.group_leader:
  151.         return CHOOSE_SECOND
  152.     elif p2.Data.group_leader:
  153.         return CHOOSE_FIRST
  154.  
  155.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  156.     if not enemy:
  157.         return CHOOSE_EITHER
  158.  
  159.     val = enemy.SQDistance2(p1) - enemy.SQDistance2(p2)
  160.  
  161.     if val < 0:
  162.         return CHOOSE_FIRST
  163.     elif val > 0:
  164.         return CHOOSE_SECOND
  165.     else:
  166.         return CHOOSE_EITHER
  167.  
  168. def ChooseFurthest (entity1name, entity2name):
  169.     p1 = Bladex.GetEntity(entity1name)
  170.     p2 = Bladex.GetEntity(entity2name)
  171.     if not p1 and not p2:
  172.         return CHOOSE_EITHER
  173.     elif not p1:
  174.         return CHOOSE_SECOND
  175.     elif not p2:
  176.         return CHOOSE_FIRST
  177.  
  178.     if p1.Life <= 0 and p2.Life <= 0:
  179.         return CHOOSE_EITHER
  180.     elif p1.Life <= 0:
  181.         return CHOOSE_SECOND
  182.     elif p2.Life <= 0:
  183.         return CHOOSE_FIRST
  184.  
  185.     # If it just comes down to distance, group leaders may order others before them
  186.     if p1.Data.group_leader:
  187.         return CHOOSE_SECOND
  188.     elif p2.Data.group_leader:
  189.         return CHOOSE_FIRST
  190.  
  191.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  192.     if not enemy:
  193.         return CHOOSE_EITHER
  194.  
  195.     val = enemy.SQDistance2(p1) - enemy.SQDistance2(p2)
  196.  
  197.     if val < 0:
  198.         return CHOOSE_SECOND
  199.     elif val > 0:
  200.         return CHOOSE_FIRST
  201.     else:
  202.         return CHOOSE_EITHER
  203.  
  204.  
  205. def ChooseMostLife (entity1name, entity2name):
  206.     p1 = Bladex.GetEntity(entity1name)
  207.     p2 = Bladex.GetEntity(entity2name)
  208.  
  209.     if not p1 and not p2:
  210.         return CHOOSE_EITHER
  211.     elif not p1:
  212.         return CHOOSE_SECOND
  213.     elif not p2:
  214.         return CHOOSE_FIRST
  215.  
  216.     if p1.Life <= 0 and p2.Life <= 0:
  217.         return CHOOSE_EITHER                          
  218.     elif p1.Life <= 0:
  219.         return CHOOSE_SECOND
  220.     elif p2.Life <= 0:
  221.         return CHOOSE_FIRST
  222.     
  223.     l1 = p1.Life
  224.     l2 = p2.Life
  225.     val = l2 - l1
  226.     if val < 0:
  227.         return CHOOSE_FIRST
  228.     elif val > 0:
  229.         return CHOOSE_SECOND
  230.     else:
  231.         return ChooseNearest (entity1name, entity2name)
  232.  
  233. def ChooseFighter (entity1name, entity2name):
  234.     p1 = Bladex.GetEntity(entity1name)
  235.     p2 = Bladex.GetEntity(entity2name)
  236.  
  237.     if not p1 and not p2:
  238.         return CHOOSE_EITHER
  239.     elif not p1:
  240.         return CHOOSE_SECOND
  241.     elif not p2:
  242.         return CHOOSE_FIRST
  243.  
  244.     if p1.Life <= 0 and p2.Life <= 0:
  245.         return CHOOSE_EITHER                          
  246.     elif p1.Life <= 0:
  247.         return CHOOSE_SECOND
  248.     elif p2.Life <= 0:
  249.         return CHOOSE_FIRST
  250.  
  251.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  252.  
  253.     if not p1.InCombat: 
  254.         if not p2.InCombat:
  255.             # Neither are in combat, just choose the closest
  256.             return ChooseNearest (entity1name, entity2name)
  257.         # Second entity is only one in combat
  258.         return CHOOSE_SECOND
  259.     elif not p2.InCombat:
  260.         # First entity is only one in combat
  261.         return CHOOSE_FIRST
  262.  
  263.     # This far means both are in combat
  264.     if not p1.CanISee(enemy):
  265.         if not p2.CanISee(enemy):
  266.             # Neither can see the enemy, but both are in combat, 
  267.             # choose the one with most life
  268.             return ChooseMostLife (entity1name, entity2name)
  269.         # Second entity is only one to see the enemy
  270.         return CHOOSE_SECOND
  271.  
  272.     elif not p2.CanISee(enemy):
  273.         # First entity is only one to see the enemy
  274.         return CHOOSE_FIRST
  275.  
  276.     # This far means both are in combat and both can see the enemy
  277.     return ChooseMostLife (entity1name, entity2name)
  278.  
  279. def ChooseLeaderOutOfCombat (entity1name, entity2name):
  280.     p1 = Bladex.GetEntity(entity1name)
  281.     p2 = Bladex.GetEntity(entity2name)
  282.  
  283.     # Best to see the other to give them orders
  284.     if p1.CanISee(p2):
  285.         if not p2.CanISee(p1):
  286.             return CHOOSE_FIRST
  287.     elif p2.CanISee(p1):
  288.         return CHOOSE_SECOND
  289.  
  290.     # Best to see the enemy next
  291.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  292.     if p1.CanISee(enemy):
  293.         if not p2.CanISee(enemy):
  294.             return CHOOSE_FIRST
  295.     elif p2.CanISee(enemy):
  296.         return CHOOSE_SECOND
  297.     
  298.     # Both or neither can see the other, 
  299.     # Both or neither can see the enemy, 
  300.     # Just choose the furthest from the enemy, 
  301.     # to order the other into combat more easily
  302.     return ChooseFurthest (entity1name, entity2name)
  303.  
  304.  
  305. def ChooseLeader (entity1name, entity2name):
  306.     p1 = Bladex.GetEntity(entity1name)
  307.     p2 = Bladex.GetEntity(entity2name)
  308.  
  309.     if not p1 and not p2:
  310.         return CHOOSE_EITHER
  311.     elif not p1:
  312.         return CHOOSE_SECOND
  313.     elif not p2:
  314.         return CHOOSE_FIRST
  315.  
  316.     if p1.Life <= 0 and p2.Life <= 0:
  317.         return CHOOSE_EITHER                          
  318.     elif p1.Life <= 0:
  319.         return CHOOSE_SECOND
  320.     elif p2.Life <= 0:
  321.         return CHOOSE_FIRST
  322.  
  323.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  324.  
  325.     if p1.Data.group_fighter:
  326.         if p2.InCombat or (p2.CanISee(enemy) and p2.GetActionMode()==ROUTE_CHASE and p2.AstarState==ASTAR_SOLVED):
  327.             return CHOOSE_SECOND
  328.         # Fighter would put himself before 
  329.         return CHOOSE_FIRST
  330.  
  331.     elif p2.Data.group_fighter:
  332.         if p1.InCombat or (p1.CanISee(enemy) and p1.GetActionMode()==ROUTE_CHASE and p1.AstarState==ASTAR_SOLVED):
  333.             return CHOOSE_FIRST
  334.         # Fighter would put himself before 
  335.         return CHOOSE_SECOND
  336.  
  337.     # This far means neither are group fighters
  338.     if not p1.InCombat: 
  339.         if not p2.InCombat:
  340.             return ChooseLeaderOutOfCombat (entity1name, entity2name)
  341.         # Second entity is only one in combat
  342.         return CHOOSE_SECOND
  343.     elif not p2.InCombat:
  344.         # First entity is only one in combat
  345.         return CHOOSE_FIRST
  346.  
  347.     # This far means neither are group fighters and both are in combat
  348.     if not p1.CanISee(enemy):
  349.         if not p2.CanISee(enemy):
  350.             # Neither can see the enemy, but both are in combat, 
  351.             # choose the one with most life
  352.             return ChooseMostLife (entity1name, entity2name)
  353.         # Second entity is only one to see the enemy
  354.         return CHOOSE_SECOND
  355.  
  356.     elif not p2.CanISee(enemy):
  357.         # First entity is only one to see the enemy
  358.         return CHOOSE_FIRST
  359.  
  360.     # This far means neither are group fighters and both are in combat 
  361.     # and both can see the enemy
  362.     return ChooseMostLife (entity1name, entity2name)
  363. ##################################################################################
  364.  
  365.  
  366.  
  367. # Define the default NPC python person class
  368. class NPCPerson (Basic_Funcs.PlayerPerson):
  369.     InvestigatingSound = FALSE
  370.     SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  371.     Asleep = FALSE
  372.     SleepYOffset = 1100.0        # this may need adjusting for non-knight chars
  373.     group_fighter=TRUE
  374.     group_leader=TRUE
  375.     AttackingNPC=FALSE
  376.     imusic_noseen_warp=0
  377.     DelayNoSeenFuncMusicBackUp=0
  378.     last_insulting_time_1AA=-1
  379.     LastThrownHurtTime=0
  380.     AttacksOwnKind=FALSE
  381.     AttackNPCTime = 5
  382.     Angry=FALSE
  383.     Furious=FALSE
  384.     ChanceOfFuryOnHurt = 0.00
  385.     ChanceOfFuryOnLeaderDeath = 0.00
  386.     ImpatientAttackTime= 5.0
  387.  
  388.  
  389.     def __init__(self, me):
  390.         Basic_Funcs.PlayerPerson.__init__(self, me)
  391.         self.SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  392.  
  393.         #_________________________________________#
  394.         #  Record some personal data              #
  395.         #_________________________________________#
  396.         AddMyWatchAnims(me.Name)
  397.         self.NPC = 1
  398.  
  399.  
  400.         #pdb.set_trace()    
  401.         self.ResetCombat(me.Name)
  402.         self.NoFXOnHit= FALSE
  403.         
  404.         
  405.         #_________________________________________#
  406.         # Initialise core                         #
  407.         #_________________________________________#
  408.         me.SubscribeToList("Listeners")
  409.         me.Deaf = 0
  410.         me.CombatGroup = "Group of " + me.Name
  411.  
  412.  
  413.         #_________________________________________#
  414.         # Set up the core functions               #
  415.         #_________________________________________#
  416.         me.SeeFunc=self.StdSeeTheEnemy
  417.         me.HearFunc=self.StdHearFunc
  418.         me.DelayNoSeenFunc=self.StdDelayNoSeen
  419.         me.NoAllowedAreaFunc=self.StdNoAllowedArea
  420.         me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  421.         me.ImHurtFunc=self.StdImHurt
  422.         me.ImDeadFunc=self.StdImDead
  423.         me.EnemyDeadFunc=self.StdEnemyDead
  424.         me.AnmEndedFunc=self.StdAnmEnded
  425.         me.EnterCloseFunc=self.StdEnterClose
  426.         me.EnterLargeFunc=self.StdEnterLarge
  427.         me.EnterPrimaryAAFunc=self.StdEnterPrimaryAA
  428.         me.EnterSecondaryAAFunc=self.StdEnterSecondaryAA
  429.         me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy         
  430.         me.ToggleCombatFunc=self.StdToggleCombat         
  431.  
  432.         # Set us up to start in the large range, so archers get your bows out!
  433.         #pdb.set_trace()
  434.         self.WeaponsOut(me.Name)
  435.  
  436.     #_________________________________________#
  437.     # Define our functions                    #
  438.     #_________________________________________#
  439.     
  440.     def ResetCombat (self,EntityName):
  441.         me = Bladex.GetEntity(EntityName)
  442.         if me and me.Life>0:
  443.             me.BlockingPropensity = 0.5
  444.             me.AttackList = []
  445.             me.CombatDistFlag = not self.group_fighter
  446.  
  447.         self.AttacksOwnKind=FALSE
  448.         self.AttackNPCTime = 5
  449.         self.Angry=FALSE
  450.         self.Furious=FALSE
  451.         self.ChanceOfFuryOnHurt = 0.00
  452.         self.ChanceOfFuryOnLeaderDeath = 0.00
  453.         self.ImpatientAttackTime= 5.0
  454.  
  455.     def StopNPCsAttacking (self,EntityName):
  456.         #print EntityName+" should stop attacking enemy now "+`Bladex.GetTime()`
  457.         # Stop both combatants        
  458.         me = Bladex.GetEntity(EntityName)
  459.         if me and me.Life>0:            
  460.             enemy = Bladex.GetEntity(me.GetEnemyName())
  461.             if enemy and enemy.Life > 0 and enemy.Data.NPC:
  462.                 enemy.Data.StopAttackingNPC (enemy.Name)
  463.         self.StopAttackingNPC (EntityName)
  464.  
  465.  
  466.     def StopAttackingNPC (self,EntityName):
  467.         if self.AttackingNPC:
  468.             self.AttackingNPC=FALSE
  469.             me = Bladex.GetEntity(EntityName)
  470.             if me and me.Life>0:
  471.                 enemy = Bladex.GetEntity(me.GetEnemyName())
  472.                 if not enemy or enemy.Data.NPC:
  473.                     enemy = Bladex.GetEntity("Player1")
  474.                     if not enemy:
  475.                         print EntityName+": Cannot access handle to Player, in StopAttackingNPC()"
  476.                         return
  477.                     #print EntityName+": Stopping attacking "+me.GetEnemyName()+" at time: "+`Bladex.GetTime()`
  478.                     Damage.DropInvalidObjectsOnImpact (EntityName)
  479.                     me.Wuea=Reference.WUEA_ENDED
  480.                     me.InterruptCombat()
  481.                     me.SetEnemy(enemy)
  482.                     MaxCombatDist = Bladex.GetCharType(me.CharType,me.CharTypeExt).MaxCombatDist
  483.                     if me.SQDistance2(enemy) < (MaxCombatDist*MaxCombatDist) or me.CanISee(enemy):
  484.                         me.SetActiveEnemy(enemy)
  485.                         me.Chase(enemy, me.ActionAreaMax)
  486.                         if me.GetActionMode()==ROUTE_CHASE and self.IsArcher():
  487.                             self.Switch2MeleeWeapons(EntityName)
  488.                     else:
  489.                         me.LaunchWatch()
  490.                         Damage.DropInvalidObjectsOnImpact (EntityName)
  491.                         me.Wuea=Reference.WUEA_ENDED
  492.                         me.LaunchAnmType("attack_look",1)
  493.                     self.CheckToJoin (EntityName)
  494.  
  495.  
  496.     #
  497.     # Standard function of ending a route
  498.     #
  499.     def StdRouteEnded(self,EntityName):        
  500.         pass
  501.             
  502.  
  503.     #
  504.     # Standard function of ending a chase without combat
  505.     #
  506.     def StdEndChase(self,EntityName):
  507.         me = Bladex.GetEntity(EntityName)
  508.         # Check I'm not dead        
  509.         if me and me.Life >0:
  510.             if not me.InCombat:
  511.                 Reference.debugprint(EntityName + ": I have ended a chase without combat (StdEndChase1)")
  512.                 enemy_pos=me.EnemyLastSeen
  513.                 if Actions.IsFacingPos(EntityName, enemy_pos[0], enemy_pos[2]):
  514.                     self.StdEndChase2(EntityName)
  515.                 else:
  516.                     Actions.TurnToFacePos(EntityName, enemy_pos[0], enemy_pos[2])
  517.                     me.RouteEndedFunc=self.StdEndChase2        # Continue when we're facing
  518.  
  519.  
  520.     def StdEndChase2(self,EntityName):
  521.         me = Bladex.GetEntity(EntityName)
  522.         # Check I'm not dead
  523.         if me and me.Life > 0:
  524.             Reference.debugprint(EntityName + ": I have ended a chase without combat (StdEndChase2)")
  525.             me.RouteEndedFunc=self.StdRouteEnded
  526.             me.StopLooking()
  527.             self.InvestigatingSound = FALSE
  528.             enemy=Bladex.GetEntity(me.GetEnemyName())
  529.             enemy_in_sight = enemy and me.CanISee(enemy)
  530.             if enemy_in_sight and enemy.InsideActionArea(me.ActionAreaMax):
  531.                 if Actions.IsFacingEntity(EntityName, me.GetEnemyName()):
  532.                     self.LaunchMyWatch (EntityName)
  533.                 else:
  534.                     Actions.TurnToFaceEntity(EntityName, me.GetEnemyName())
  535.                     me.RouteEndedFunc=self.LaunchMyWatch
  536.             else:        
  537.                 if enemy_in_sight:
  538.                     self.StdSeeEnemyUnreachable (EntityName)
  539.                 else:
  540.                     Damage.DropInvalidObjectsOnImpact (EntityName)
  541.                     me.Wuea=Reference.WUEA_ENDED
  542.                     if me.GetActionMode() != ROUTE_WATCH:
  543.                         self.LaunchMyWatch (EntityName)
  544.                     me.LaunchAnmType("look_around",1)
  545.                 # The enemy has disappeared for us around here
  546.                 # If we cannot find him, change our behaviour from the standard no seen function
  547.                 me.DelayNoSeenFunc=self.EndChaseDelayNoSeen
  548.                 if me.Data.imusic_noseen_warp==1:
  549.                     DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  550.  
  551.     def PutMeToSleep(self,EntityName):
  552.         if not self.Asleep:
  553.             me = Bladex.GetEntity(EntityName)
  554.             me.SetTmpAnmFlags(1,1,0,0,1,1) 
  555.             # doesn't work for the traitor knight, so just call the Tkn version instead!
  556.             #We need to move the char down as well to touch the floor
  557.             me.Position = (me.Position[0], me.Position[1]+self.SleepYOffset, me.Position[2])
  558.             me.LaunchAnimation("Tkn_sleep")
  559.             me.Blind=1  #just in case
  560.             self.Asleep = TRUE
  561.  
  562.     def WakeMeUp(self,EntityName):
  563.         if self.Asleep:
  564.             me = Bladex.GetEntity(EntityName)
  565.             me.Blind=0  #just in case
  566.             # alert animation
  567.             me.Position = (me.Position[0], me.Position[1]-(self.SleepYOffset*0.5), me.Position[2])
  568.             if me.AnimName[:5] == "Sleep" or me.AnimName[:5] == "sleep":
  569.                 me.Wuea=Reference.WUEA_ENDED
  570.                 me.LaunchAnmType("alarm01",1)
  571.             self.Asleep = FALSE
  572.  
  573.     #  
  574.     # Standard function of trying to initialise a chase, 
  575.     #
  576.     def StdStartChase(self,EntityName):
  577.         me = Bladex.GetEntity(EntityName)
  578.         enemy=Bladex.GetEntity(me.GetEnemyName())
  579.         me.AnmEndedFunc=self.StdAnmEnded
  580.         #enemy_pos=enemy.Position
  581.         #me.StartLooking(enemy_pos[0], enemy_pos[1], enemy_pos[2])
  582.         if enemy.InsideActionArea(me.ActionAreaMax) or (self.IsArcher() and me.InsideActionArea(me.ActionAreaMax)):
  583.             self.StdStartChase2 (EntityName)
  584.         else:
  585.             # The following is to turn to face the enemy when we are already at an illegal border
  586.             self.StdSeeEnemyUnreachable (EntityName)
  587.  
  588.     def StdSeeEnemyUnreachable(self,EntityName,check1aaTo2aa=1):
  589.         me = Bladex.GetEntity(EntityName)
  590.         Reference.debugprint(EntityName + ": Enemy Unreachable")
  591.         if Bladex.GetTime()-self.LastThrownHurtTime<THROWNHURTTIME_GAP:
  592.             return
  593.                 
  594.         if me.InsideActionArea(me.ActionAreaMin) and (check1aaTo2aa and not me.Will1aaTo2aa):
  595.             back_area_min=me.ActionAreaMin
  596.             back_area_max=me.ActionAreaMax
  597.             me.ActionAreaMin=0
  598.             me.ActionAreaMax=0
  599.             enemy=Bladex.GetEntity(me.GetEnemyName())
  600.             des_pos=enemy.Position
  601.             me.GoToJogging=1
  602.             if me.GoTo(des_pos[0],des_pos[1],des_pos[2]):
  603.                 me.ActionAreaMin=back_area_min
  604.                 me.ActionAreaMax=back_area_max
  605.             else: 
  606.                 Reference.debugprint(EntityName + ": GoTo enemy_pos not working, with action area 0!")
  607.                 me.ActionAreaMin=back_area_min
  608.                 me.ActionAreaMax=back_area_max
  609.             return
  610.  
  611.         elif me.InsideActionArea(me.ActionAreaMin):
  612.             if me.GetActionMode() != ROUTE_WATCH:
  613.                 self.LaunchMyWatch (EntityName)
  614.             if not Actions.IsFacingEntity(EntityName, me.GetEnemyName()):
  615.                 Actions.TurnToFaceEntity(EntityName, me.GetEnemyName())
  616.             else:
  617.                 curr_time=Bladex.GetTime()
  618.                 if curr_time-self.last_insulting_time_1AA>4:
  619.                     insult_prob=whrandom.uniform(0.0, 1.0)
  620.                     if insult_prob<0.8:
  621.                         Combat.Insult(EntityName)
  622.                     insult_var=whrandom.uniform(-2.0, 1.0)
  623.                     self.last_insulting_time_1AA=Bladex.GetTime()+insult_var
  624.         else:
  625.             back_area_min=me.ActionAreaMin
  626.             back_area_max=me.ActionAreaMax
  627.             me.ActionAreaMax= 0
  628.             me.ActionAreaMin= 0
  629.             
  630.             init_pos=me.InitPos
  631.             me.InvertedRoute=1 # Move backwards
  632.             if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  633.                 me.ActionAreaMin=back_area_min
  634.                 me.ActionAreaMax=back_area_max
  635.             else:
  636.                 Reference.debugprint(EntityName + ": GoTo init_pos not working, with action area 0!")
  637.                 me.ActionAreaMin=back_area_min
  638.                 me.ActionAreaMax=back_area_max
  639.             
  640.  
  641.     def StdStartChase2(self,EntityName):
  642.         me = Bladex.GetEntity(EntityName)
  643.         enemy=Bladex.GetEntity(me.GetEnemyName())
  644.         oldActionMode = me.GetActionMode()        
  645.         if (oldActionMode == ROUTE_WATCH) or (oldActionMode == ROUTE_BOWING):
  646.             # We could have got here after turning, so reset the RouteEndedFunc.
  647.             me.RouteEndedFunc=self.StdRouteEnded
  648.         if oldActionMode == ROUTE_CHASE:
  649.             pass
  650.         else:
  651.             self.ResetCombat(EntityName)
  652.             last_time_seen=me.LastTimeSeen       #Note that the "Chase" function updates the LastSeenTime!
  653.             me.Chase(enemy, me.ActionAreaMax)
  654.             if me.GetActionMode()==ROUTE_CHASE:
  655.                 if self.IsArcher():
  656.                     self.Switch2MeleeWeapons(EntityName)
  657.                 else:
  658.                     if Bladex.GetTime()-last_time_seen>40 or last_time_seen<0:
  659.                         me.LaunchAnmType("alarm01",1)
  660.                     #else:
  661.                     #    print "Too early to alarm..." + str(me.LastTimeSeen)
  662.  
  663.                 self.InvestigatingSound = FALSE
  664.                 me.RouteEndedFunc=self.StdEndChase 
  665.                 if me.Aim or Actions.CurrentlyBowing(EntityName):
  666.                     me.Wuea=Reference.WUEA_ENDED
  667.                     Actions.EndBowMode(EntityName)
  668.             else:
  669.                 self.StdChaseFailed (EntityName, oldActionMode)
  670.  
  671.  
  672.     # Is Chase() going to put us in BOWING mode when it fails
  673.     def IsArcher(self):                            # Needs to more sopisticated when inventory is working
  674.         return Actions.StatL(self.Name)==Actions.RA_BOW
  675.         
  676.  
  677.     def StdChaseFailed(self,EntityName, oldActionMode):    # Try to restore our state to whatever we were doing before attempting to chase    
  678.         me = Bladex.GetEntity(EntityName)
  679.         newActionMode = me.GetActionMode()
  680.         if newActionMode == ROUTE_BOWING:
  681.             Reference.debugprint(EntityName + ": I cannot start a chase so I will bow")    
  682.             pass
  683.         #NOTA : R_WATCH incluye _BAY (al fallar un GoTo desde una W_BAY se pasa AUTOMATICAMEnTE a watch!!!)
  684.         elif oldActionMode == ROUTE_WATCH:
  685.             Reference.debugprint(EntityName + ": I cannot start a chase so I will watch again")
  686.             self.LaunchMyWatch(EntityName)
  687.  
  688.             enemy=Bladex.GetEntity(me.GetEnemyName())
  689.             if enemy and me.CanISee(enemy) and me.InsideActionArea(me.ActionAreaMin):
  690.                 inv = me.GetInventory()
  691.                 if inv.HasBow and me.RangeActive:
  692.                     #print "StdChaseFailed-> Just facing due to carry bow"
  693.                     enemy_pos=me.EnemyLastSeen
  694.                     if not Actions.IsFacingPos(EntityName, enemy_pos[0], enemy_pos[2]):
  695.                         Actions.TurnToFacePos(EntityName, enemy_pos[0], enemy_pos[2])
  696.                 else:
  697.                     self.StdSeeEnemyUnreachable (EntityName,0)
  698.  
  699.         
  700.  
  701.     def GiveOrders (self, EntityName):
  702.         me=Bladex.GetEntity(EntityName)
  703.         if me and me.Life>0 and self.NextOrdersTo and self.NextOrders:
  704.             me.Wuea=Reference.WUEA_ENDED
  705.             me.SetTmpAnmFlags(1,0,1,0,1,1) 
  706.             me.LaunchAnmType("order",1)
  707.             me.AnmEndedFunc=self.GiveOrders2
  708.  
  709.     def GiveOrders2 (self, EntityName):
  710.         me=Bladex.GetEntity(EntityName)
  711.         if me and self.NextOrdersTo and self.NextOrders:
  712.             for name in self.NextOrdersTo:
  713.                 self.NextOrders(name)
  714.  
  715.     def CheckToJoin (self, EntityName):
  716.         ##startmem = BDAux.GetAvailablePhysicalMemory()
  717.         me = Bladex.GetEntity(EntityName)
  718.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  719.         ##    pdb.set_trace()
  720.         # Get a list of the enemies of my enemy currently in combat
  721.         #pdb.set_trace()
  722.         ally_list = me.GetCombatants()
  723.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  724.         ##    pdb.set_trace()
  725.         for ally_name in ally_list:
  726.             if ally_name != EntityName:    # Cannot really happen I think
  727.                 ally = Bladex.GetEntity (ally_name)
  728.                 if ally:
  729.                     if me.CombatGroup != ally.CombatGroup:
  730.                         self.JoinGroup (EntityName, ally.CombatGroup)
  731.                     return
  732.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  733.         ##    pdb.set_trace()
  734.  
  735.         self.CheckGoodGroupFormation (EntityName, TRUE)        
  736.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  737.         ##    pdb.set_trace()
  738.  
  739.     def JoinGroup (self, EntityName, GroupName):
  740.         me = Bladex.GetEntity(EntityName)
  741.         # Joining Group Logic
  742.         me.CombatGroup = GroupName
  743.         self.group_fighter = FALSE
  744.         self.group_leader  = FALSE
  745.         if not self.Furious:
  746.             me.CombatDistFlag = 1        # move out
  747.         self.CheckGoodGroupFormation (EntityName, TRUE)
  748.  
  749.     def LeaveGroup(self, EntityName):
  750.         # Make sure the group we are leaving has a fighter and a leader
  751.         me = Bladex.GetEntity(EntityName)
  752.         if self.group_fighter or self.group_leader:
  753.             self.SetGroupFormation(EntityName, FALSE, self.group_leader)
  754.         NewCombatGroup = "Group of " + me.Name
  755.         if me.CombatGroup == NewCombatGroup:
  756.             NewCombatGroup= NewCombatGroup + '... Splitters'
  757.         me.CombatGroup = NewCombatGroup
  758.         self.group_leader = TRUE
  759.         self.group_fighter = TRUE
  760.  
  761.  
  762.     #
  763.     # Standard function of seeing an enemy 
  764.     #
  765.     def StdSeeTheEnemy(self,EntityName):
  766.         me = Bladex.GetEntity(EntityName)
  767.         Reference.debugprint (EntityName + ": I see the enemy");
  768.         life = me.Life
  769.         if life > 0.0:        # Check I'm not dead
  770.             if me.Blind==1:
  771.                 pass
  772.             else:
  773.                 me.LookAtEntity(me.GetEnemyName())
  774.                 
  775.                 #Just in case we were doing a wait animation
  776.                 if me.GetActionMode() == ROUTE_BAY:    
  777.                     me.Wuea=Reference.WUEA_ENDED
  778.  
  779.                 self.CheckToJoin(EntityName)
  780.                 if me.GetActionMode()!=ROUTE_CHASE:
  781.                     self.StdStartChase(EntityName)
  782.                 
  783.                 if me.GetActionMode()==ROUTE_BOWING: 
  784.                     if self.AimPressed:
  785.                         angle= Reference.TARGET_ANGLE_MAX- me.Accuracy*(Reference.TARGET_ANGLE_MAX-Reference.TARGET_ANGLE_MIN)
  786.                         if me.AimOffTarget<angle:
  787.                             print "Releasing Arrow"
  788.                             Actions.TestReleaseArrow(EntityName)
  789.                     else: 
  790.                         if me.Wuea!=Reference.WUEA_WAIT:
  791.                             print "Drawing Bow"
  792.                             Actions.TestDrawBow (EntityName)
  793.                 elif me.Aim or Actions.CurrentlyBowing(EntityName):
  794.                     me.Wuea=Reference.WUEA_ENDED
  795.                     Actions.EndBowMode(EntityName)
  796.                     me.SetOnFloor()
  797.         else:
  798.             print (EntityName + ": Cannot get a handle on me")
  799.     #
  800.     # Standard function of hearing an enemy 
  801.     #
  802.     # make a default database here.  Other entities can have other databases...
  803.     # Sonidas Flechas (Arrow sounds)
  804.     # Objeto Arrojado o golpeado (thrown objects or hitting sounds)
  805.     # Sonido de enemigo.  Por grito o herida (Other NPCs shouting, or injured)
  806.     # Sonido de personaje ojando no esta en modo siglo (pisadas) (PC sounds when they're not walking silently -- footsteps)
  807.     # Gritas de atao o herida (Battle cries or injuries of the PC)
  808.  
  809.     def GetSoundType(self, SoundName):
  810.         if Reference.SoundTypes.has_key(SoundName):
  811.             return Reference.SoundTypes[SoundName][0]
  812.         return Reference.SND_UNCLASSIFIED
  813.         
  814.     def GetSoundPriority (self, EntityName,  SoundName, Volume):
  815.         me = Bladex.GetEntity(EntityName)
  816.         # Check against our sound tables
  817.         priority = Reference.SND_UNCLASSIFIED        # look this up in a dictionary for our race, or -1.0 if not present
  818.         sound_type= self.GetSoundType(SoundName)
  819.         if sound_type != Reference.SND_UNCLASSIFIED:
  820.             priority = self.SoundPriorities [sound_type]
  821.             # volume should be between 0.0 and 1.0 or an order of magnitude smaller 
  822.             # than the base priority.  Scale it down to be sure
  823.             return  priority + (Volume * 0.01)
  824.         
  825.     def IsSoundHigherPriority (self, EntityName, SoundName, Volume):
  826.         me = Bladex.GetEntity(EntityName)
  827.         priority = self.GetSoundPriority (EntityName, SoundName, Volume)
  828.         if priority <= 0.0:    # if we're not interested in this kind of sound:
  829.             return FALSE        
  830.         elif (not self.InvestigatingSound) or (me.GetActionMode()!=ROUTE_SINGLE):
  831.             return TRUE
  832.         else:
  833.             investigating_priority = self.GetSoundPriority (EntityName, self.InvestigatingSoundName, self.InvestigatingSoundVolume)
  834.             return priority > investigating_priority
  835.  
  836.     def StdInvestigateSound(self,EntityName):
  837.         me = Bladex.GetEntity(EntityName)
  838.         if me and me.Life > 0:
  839.             me.StartLooking(self.InvestigatingSoundX, self.InvestigatingSoundY, self.InvestigatingSoundZ)
  840.             Reference.debugprint (EntityName + ": Im going to investigate "+self.InvestigatingSoundName+" at pos "+`self.InvestigatingSoundX`+", "+`self.InvestigatingSoundY`+", "+`self.InvestigatingSoundZ`);
  841.             me.GoToSneaking=1
  842.             me.GoTo(self.InvestigatingSoundX,self.InvestigatingSoundY,self.InvestigatingSoundZ)
  843.  
  844.             if me.AstarState<>ASTAR_SOLVED:
  845.                 # We cannot get there, just look at the source of the sound instead
  846.                 me.GoToSneaking=0
  847.                 if Actions.IsFacingPos(EntityName, self.InvestigatingSoundX, self.InvestigatingSoundZ):
  848.                     self.LaunchMyWatch (EntityName)
  849.                 else:
  850.                     Actions.TurnToFacePos(EntityName, self.InvestigatingSoundX, self.InvestigatingSoundZ)
  851.                     me.RouteEndedFunc=self.LaunchMyWatch
  852.             else:
  853.                 # We can use the same end func as ending a chase
  854.                 me.Heard = TRUE
  855.                 me.RouteEndedFunc=self.StdEndChase2
  856.  
  857.     def CanGoTo (self, EntityName, x, y, z):
  858.         me = Bladex.GetEntity(EntityName)
  859.         if me and me.Life > 0:
  860.             me.GoTo(x,y,z)
  861.             if me.AstarState==ASTAR_SOLVED:
  862.                 me.LaunchWatch()
  863.                 return TRUE
  864.         return FALSE
  865.  
  866.  
  867.     def StdHearFunc(self,EntityName, SoundName, x, y, z, Volume):
  868.         me = Bladex.GetEntity(EntityName)
  869.         
  870.         if me and me.Life > 0 and me.Deaf<>1:
  871. ##            try:
  872.                 # Is the sound below audible range
  873.                 if Volume < Bladex.GetCharType(me.CharType,me.CharTypeExt).HearMinVolume:
  874.                     return
  875.                 
  876.                 # No need to bother responding if we're already in combat
  877.                 if me.InCombat:
  878.                     return
  879.                 
  880.                 if DEBUG_SOUNDS:
  881.                     pdb.set_trace()
  882.                 sound_type= self.GetSoundType(SoundName)
  883.                 
  884.                 # Is the sound unknown
  885.                 if sound_type==Reference.SND_UNCLASSIFIED:
  886.                     return
  887.                 
  888.                 # If our enemy is dead, don't bother going to investigate
  889.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  890.                 if (not enemy) or (not enemy.Person) or enemy.Life <= 0:
  891.                     return
  892.                     
  893.                 # for footsteps etc, Check they belong to the player, not realistic, but quick
  894.                 if sound_type==Reference.SND_NOISYPC:
  895.                     #if self.GroupCoveringPoint (EntityName, x, y, z, FALSE):
  896.                     #    return
  897.                     if enemy.LastSound != SoundName:
  898.                         return
  899.                     
  900.                     elsp= enemy.LastSoundPosition
  901.                     if elsp[0]!= x or elsp[1]!=y or elsp[2]!=z:
  902.                         return
  903.                 
  904.                 # Was the sound generated by oureself
  905.                 #if me.TestPosInOwnBox (x, y, z, 1.05):
  906.                 if me.LastSound==SoundName:
  907.                     lsp= me.LastSoundPosition
  908.                     if lsp[0]== x and lsp[1]==y and lsp[2]==z:
  909.                         return
  910.                 
  911.                 # Is the sound from our last thrown hurt ?
  912.                 if Bladex.GetTime()-self.LastThrownHurtTime<THROWNHURTTIME_GAP*0.5:
  913.                     return    
  914.                 
  915.                 # The see functions will take care of this
  916.                 if me.CanISee(enemy):
  917.                     return
  918.                     
  919.                 if self.Asleep:
  920.                     self.WakeMeUp(EntityName)
  921.  
  922.                 if me.GetActionMode() == ROUTE_BAY and me.CanGoTo(x,y,z)==0:
  923.                     #print "StdHearFunc, debug - BAY stuff..."
  924.                     return 
  925.  
  926.                 
  927.                 if self.group_leader:
  928.                     # record that we have dealt with the sound
  929.                     self.DealtWithSound= SoundName
  930.                     self.DealtWithSoundX= x
  931.                     self.DealtWithSoundY= y
  932.                     self.DealtWithSoundZ= z
  933.                     
  934.                     # Assign an investigator
  935.                     investigator = self.GetGroupFighter(EntityName)
  936.                     if (not investigator) or investigator.GetActionMode()==ROUTE_CHASE or investigator.InCombat:
  937.                         investigator = me
  938.                 else:
  939.                     group_leader = self.GetGroupLeader(EntityName)
  940.                     if group_leader and not (group_leader.InCombat or group_leader.GetActionMode()==ROUTE_CHASE):
  941.                         # does the leader know already?
  942.                         try:
  943.                             ldr_data= group_leader.Data
  944.                             if SoundName==ldr_data.DealtWithSound and x==ldr_data.DealtWithSoundX and y==ldr_data.DealtWithSoundY and z==ldr_data.DealtWithSoundZ:
  945.                                 return
  946.                         except:
  947.                             pass
  948.                         group_leader.HearFunc(group_leader.Name, SoundName, x, y, z, Volume)
  949.                         # leader will tell investigator what to do
  950.                         # but we can take the initiative to turn around
  951.                         if (not me.InCombat) and (me.GetActionMode()!=ROUTE_CHASE):
  952.                             if not Actions.IsFacingPos(EntityName, x, z):
  953.                                 Actions.QuickTurnToFacePos(EntityName, x, z)
  954.                         return
  955.                     else:
  956.                         # leader is busy, investigate ourself
  957.                         investigator = me
  958.     
  959.                 if investigator.Data.InvestigatingSound and SoundName == investigator.Data.InvestigatingSoundName and x == investigator.Data.InvestigatingSoundX and y == investigator.Data.InvestigatingSoundY and z == investigator.Data.InvestigatingSoundZ:
  960.                     # investigator is already investigating this sound        
  961.                     return 
  962.                 elif investigator.Data.IsSoundHigherPriority(investigator.Name, SoundName, Volume) and investigator.GetActionMode()!=ROUTE_CHASE and not investigator.InCombat:
  963.                     me.StartLooking(x, y, z)
  964.     
  965.                     # Turn to face the sound
  966.                     if not Actions.IsFacingPos(EntityName, x, z):
  967.                         Actions.QuickTurnToFacePos(EntityName, x, z)
  968.  
  969.  
  970.                     # React to the sound, with alarm
  971.                     if investigator.Name != EntityName: 
  972.                         # Tell investigator to turn to face the sound
  973.                         if not Actions.IsFacingPos(investigator.Name, x, z):
  974.                             Actions.QuickTurnToFacePos(investigator.Name, x, z)
  975.                         
  976.                         if (not investigator.Data.InvestigatingSound):
  977.                             if (me.AnimName[:4] != "hurt" and me.AnimName[:5] != "sleep"):
  978.                                 if investigator.Data.CanGoTo(investigator.Name, x, y, z):
  979.                                     me.Wuea=Reference.WUEA_ENDED
  980.                                     me.SetTmpAnmFlags(1,0,1,0,1,1) 
  981.                                     me.LaunchAnmType("alarm01",1)
  982.     
  983.                     # Send off fighter to investigate
  984.                     investigator.Data.InvestigatingSound = TRUE
  985.                     investigator.Data.InvestigatingSoundName = SoundName
  986.                     investigator.Data.InvestigatingSoundVolume = Volume
  987.                     investigator.Data.InvestigatingSoundX = x
  988.                     investigator.Data.InvestigatingSoundY = y
  989.                     investigator.Data.InvestigatingSoundZ = z
  990.     
  991.                     if me.AnimName=="alarm01":
  992.                         if EntityName != investigator.Name:
  993.                             self.NextOrdersTo = []
  994.                             self.NextOrdersTo.append(investigator.Name)
  995.                             self.NextOrders = investigator.Data.StdInvestigateSound
  996.                             me.AnmEndedFunc=self.GiveOrders
  997.                         else:
  998.                             me.AnmEndedFunc=self.StdInvestigateSound
  999.                     else:
  1000.                         if EntityName != investigator.Name:
  1001.                             self.NextOrdersTo = []
  1002.                             self.NextOrdersTo.append(investigator.Name)
  1003.                             self.NextOrders = investigator.Data.StdInvestigateSound
  1004.                             self.GiveOrders (EntityName)
  1005.                         else:
  1006.                             self.StdInvestigateSound (EntityName)
  1007. ##            except TypeError,detail:
  1008. ##                print "TypeError Exception",detail
  1009. ##                pdb.set_trace()
  1010.  
  1011.  
  1012.     #
  1013.     # Aux funcs
  1014.     #
  1015.  
  1016.     def LaunchMyWatch(self,EntityName):
  1017.         me = Bladex.GetEntity(EntityName)
  1018.         if me and me.Life > 0:
  1019.             enemy=Bladex.GetEntity(me.GetEnemyName())
  1020.             if not enemy or not me.CanISee(enemy):
  1021.                 me.StopLooking()
  1022.  
  1023.             #Just in case . This is the best place 4 this
  1024.             me.GoToJogging=0
  1025.             me.GoToSneaking=0
  1026.  
  1027.             me.LaunchWatch()
  1028.  
  1029.  
  1030.     def Turn180AndWatch(self,EntityName):
  1031.         me = Bladex.GetEntity(EntityName)
  1032.         Actions.Turn180(EntityName)
  1033.         me.RouteEndedFunc=self.LaunchMyWatch
  1034.  
  1035.     def LaunchMyPatrol(self,EntityName):
  1036.         me = Bladex.GetEntity(EntityName)
  1037.         me.StopLooking()
  1038.  
  1039.         init_pos=me.InitPos
  1040.         my_pos=me.Position
  1041.         x = init_pos[0] - my_pos[0]
  1042.         z = init_pos[2] - my_pos[2]
  1043.         DiscountDistance = 1000.0  #Used 2b 500
  1044.         if (not me.InsideActionArea(me.ActionAreaMin)) or (x*x+z*z)>(DiscountDistance*DiscountDistance):
  1045.             me.GoTo(init_pos[0],init_pos[1],init_pos[2])
  1046.             Reference.debugprint(EntityName+": Going 2 InitPos - self.LaunchMyPatrol")
  1047.             me.RouteEndedFunc=self.Turn180AndWatch
  1048.         else:
  1049.             Reference.debugprint(EntityName+": Not back2init cause quite close and inside MinAA")
  1050.             pass
  1051.         
  1052.     #
  1053.     # Standard function of what to do when the enemy is out of sight for some time 
  1054.     #
  1055.     def StdDelayNoSeen(self,EntityName):
  1056.         ##startmem = BDAux.GetAvailablePhysicalMemory()
  1057.         me = Bladex.GetEntity(EntityName)
  1058.         # Check I'm not dead
  1059.         if me.Life > 0:
  1060.             if (not self.Asleep) and (not me.Blind):
  1061.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1062.                 ##    pdb.set_trace()
  1063.  
  1064.                 if me.Aim or Actions.CurrentlyBowing(EntityName):
  1065.                     me.Wuea=Reference.WUEA_ENDED
  1066.                     Actions.EndBowMode(EntityName)
  1067.                     me.SetOnFloor()
  1068.  
  1069.                 Reference.debugprint(EntityName+": Im in StdDelayNoSeen")
  1070.                 #self.SetGroupFormation (EntityName, TRUE, FALSE)
  1071.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1072.                 ##    pdb.set_trace()
  1073.  
  1074.                 me.StopLooking()
  1075.                 enemy_name=me.GetEnemyName()
  1076.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1077.                 ##    pdb.set_trace()
  1078.  
  1079.                 enemy=Bladex.GetEntity(enemy_name)
  1080.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1081.                 ##    pdb.set_trace()
  1082.                 
  1083.                 if me.GetActionMode() != ROUTE_CHASE:
  1084.                     if me.GetActionMode() != ROUTE_SINGLE and me.GetActionMode() != ROUTE_BAY:
  1085.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1086.                         ##    pdb.set_trace()
  1087.  
  1088.                         Reference.debugprint(EntityName+": I am not chasing")
  1089.                         self.LaunchMyPatrol(EntityName)
  1090.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1091.                         ##    pdb.set_trace()
  1092.  
  1093.                 else:
  1094.                     Reference.debugprint(EntityName+": I am chasing")
  1095.                     if me.AstarState<>ASTAR_SOLVED:
  1096.                         # Face enemy as much as possible
  1097.                         lastseenpos = me.EnemyLastSeen
  1098.                         me.StartLooking(lastseenpos[0], lastseenpos[1], lastseenpos[2])
  1099.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1100.                         ##    pdb.set_trace()
  1101.  
  1102.                         if Actions.IsFacingPos(EntityName, lastseenpos[0], lastseenpos[2]):
  1103.                             self.LaunchMyWatch (EntityName)
  1104.                             ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1105.                             ##    pdb.set_trace()
  1106.  
  1107.                         else:
  1108.                             Actions.TurnToFacePos(EntityName, lastseenpos[0], lastseenpos[2])
  1109.                             me.RouteEndedFunc=self.LaunchMyWatch
  1110.                             ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1111.                             ##    pdb.set_trace()
  1112.  
  1113.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1114.         ##    pdb.set_trace()
  1115.  
  1116.     #
  1117.     # Alternate function if we've just ended a chase and the enemy is out of sight for some time
  1118.     #
  1119.     def EndChaseDelayNoSeen(self,EntityName):
  1120.         me = Bladex.GetEntity(EntityName)
  1121.         Reference.debugprint(EntityName + ": Im in EndChaseDelayNoSeen!")
  1122.         # Check I'm not dead
  1123.         if me.Life > 0:
  1124.             me.DelayNoSeenFunc=self.StdDelayNoSeen
  1125.             self.StdDelayNoSeen(EntityName)
  1126.             if me.Data.imusic_noseen_warp==1:
  1127.                 DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  1128.  
  1129.  
  1130.     #
  1131.     # Standard function for entering a non allowed area (see the "Action Areas" thing)
  1132.     #
  1133.     def StdNoAllowedArea(self,EntityName):
  1134.         me = Bladex.GetEntity(EntityName)
  1135.         Reference.debugprint(EntityName + ": Im entering non-allowed area!")
  1136.         back_area_min=me.ActionAreaMin
  1137.         back_area_max=me.ActionAreaMax
  1138.         me.ActionAreaMin=0
  1139.         me.ActionAreaMax=0
  1140.         init_pos=me.InitPos
  1141.         me.InvertedRoute=0
  1142.         if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  1143.             me.ActionAreaMin=back_area_min
  1144.             me.ActionAreaMax=back_area_max
  1145.         
  1146.  
  1147.     #
  1148.     # Standard function for when the enemy BEING CHASED (imp!) enters a non allowed area
  1149.     #
  1150.     def StdEnemyNoAllowedArea(self,EntityName):
  1151.         me = Bladex.GetEntity(EntityName)
  1152.         enemy=Bladex.GetEntity(me.GetEnemyName())
  1153.         
  1154.         if me.GetActionMode()<>ROUTE_CHASE:
  1155.             return
  1156.  
  1157.         init_pos=me.InitPos
  1158.         if (not me.InsideActionArea(me.ActionAreaMin)) and me.InsideActionArea(me.ActionAreaMax):
  1159.             me.InvertedRoute=1
  1160.         else:
  1161.             me.InvertedRoute=0
  1162.         me.GoTo(init_pos[0],init_pos[1],init_pos[2])
  1163.         Reference.debugprint(EntityName + ": My enemy has entered a non-allowed area")
  1164.  
  1165.     #
  1166.     # Standard function for taking injury
  1167.     #
  1168.     def StdImHurt(self,EntityName):
  1169.         Reference.debugprint(EntityName+": Oh! That hurt.")
  1170.         me = Bladex.GetEntity(EntityName)
  1171.         #
  1172.         # Rest of stuff
  1173.         #
  1174.         if self.NPC==0:
  1175.             return
  1176.  
  1177.         if self.Asleep:
  1178.             self.WakeMeUp(EntityName)
  1179.  
  1180.         #if me.GetActionMode() == ROUTE_WATCH:
  1181.         #    print "See due2 being hurt"
  1182.         #    me.SeeFunc(EntityName)
  1183.  
  1184.  
  1185.     #
  1186.     # Combat Group Functions
  1187.     #
  1188.     def GroupCoveringPoint (self, EntityName, x, y, z, include_me=TRUE):
  1189.         me = Bladex.GetEntity(EntityName)
  1190.         if me.CombatGroup:
  1191.             memberlist = me.GetGroupMembers()
  1192.             for member_name in memberlist:
  1193.                 if include_me or member_name != EntityName:
  1194.                     member = Bladex.GetEntity (member_name)
  1195.                     if member.TestPosInOwnBox (x, y, z, 1.05):
  1196.                         return TRUE
  1197.         elif include_me:
  1198.             return me.TestPosInOwnBox (x, y, z, 1.05)
  1199.         return FALSE
  1200.     
  1201.     def GetGroupLeader (self, EntityName):
  1202.         me = Bladex.GetEntity(EntityName)
  1203.         if me.CombatGroup:
  1204.             memberlist = me.GetGroupMembers()
  1205.             for member_name in memberlist:
  1206.                 member = Bladex.GetEntity (member_name)
  1207.                 if member and member.Life > 0 and member.Data.group_leader:
  1208.                     return member
  1209.         return None
  1210.  
  1211.     def GetGroupFighter (self, EntityName):
  1212.         me = Bladex.GetEntity(EntityName)
  1213.         if me.CombatGroup:
  1214.             memberlist = me.GetGroupMembers()
  1215.             for member_name in memberlist:
  1216.                 member = Bladex.GetEntity (member_name)
  1217.                 if member and member.Life > 0 and member.Data.group_fighter:
  1218.                     return member
  1219.         return None
  1220.  
  1221.  
  1222.     def CheckGoodGroupFormation(self,EntityName, include_me):
  1223.         me = Bladex.GetEntity(EntityName)
  1224.  
  1225.         if me.CombatGroup:
  1226.             memberlist = me.GetGroupMembers()
  1227.             if len(memberlist) > 1:
  1228.                 fighter_found = None
  1229.                 leader_found = None
  1230.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  1231.                 for member_name in memberlist:
  1232.                     if include_me or member_name != EntityName:
  1233.                         member = Bladex.GetEntity (member_name)
  1234.  
  1235.                         if (not leader_found) and member and member.Data.group_leader and member.Life > 0:
  1236.                             if (not member.Data.group_fighter) and (not member.Data.Furious):
  1237.                                 member.CombatDistFlag = 1
  1238.                             leader_found = member.Name
  1239.                         else:
  1240.                             member.Data.group_leader = FALSE
  1241.  
  1242.                         if (not fighter_found) and member and member.Data.group_fighter and member.Life > 0 and enemy and member.CanISee(enemy):
  1243.                             member.CombatDistFlag = 0
  1244.                             fighter_found = member.Name
  1245.                         else:
  1246.                             if member.Data.group_fighter:
  1247.                                 if not member.Data.Furious:
  1248.                                     member.CombatDistFlag = 1
  1249.                                 member.Data.group_fighter = FALSE
  1250.  
  1251.                 if fighter_found and leader_found and (fighter_found != leader_found):
  1252.                     return
  1253.  
  1254.                 # If we get to this point then we're either missing a group leader or a group fighter
  1255.                 self.SetGroupFormation (EntityName, include_me, not leader_found)
  1256.     
  1257.             else:
  1258.                 if include_me:
  1259.                     self.group_leader= TRUE
  1260.                     self.group_fighter= TRUE
  1261.                     me.CombatDistFlag= 0
  1262.                 return
  1263.  
  1264.     def CallGroupMemberFunc(self,EntityName, func, include_me):
  1265.         me = Bladex.GetEntity(EntityName)
  1266.         if me and me.Life >0 and me.CombatGroup:
  1267.             memberlist = me.GetGroupMembers()
  1268.             if (not include_me) and memberlist.count(EntityName) > 0:
  1269.                 memberlist.remove(EntityName)
  1270.             for member_name in memberlist:
  1271.                 func (member_name)
  1272.  
  1273.     def SetNoGroupFighter(self,EntityName):    
  1274.         me = Bladex.GetEntity(EntityName)
  1275.         if me.CombatGroup:
  1276.             memberlist = me.GetGroupMembers()
  1277.             for member_name in memberlist:
  1278.                 member = Bladex.GetEntity (member_name)
  1279.                 if not member.Data.Furious:
  1280.                     member.CombatDistFlag = 1
  1281.                 member.Data.group_fighter = FALSE
  1282.  
  1283.     def SetNoGroupLeader(self,EntityName):    
  1284.         me = Bladex.GetEntity(EntityName)
  1285.         if me.CombatGroup:
  1286.             memberlist = me.GetGroupMembers()
  1287.             for member_name in memberlist:
  1288.                 member = Bladex.GetEntity (member_name)
  1289.                 member.Data.group_leader = FALSE
  1290.  
  1291.     def SetGroupFormation(self,EntityName, include_me, new_leader_needed):    
  1292.         if new_leader_needed:
  1293.             self.SetGroupLeader (EntityName, include_me)
  1294.         self.SetGroupFighter (EntityName, include_me)
  1295.  
  1296.     def SetGroupFighter(self,EntityName, include_me):
  1297.         me = Bladex.GetEntity(EntityName)
  1298.         if me.CombatGroup:
  1299.             self.SetNoGroupFighter (EntityName)
  1300.             # Can I find someone else to go in close range        
  1301.             memberlist = me.GetGroupMembers()
  1302.             if (not include_me) and memberlist.count(EntityName) > 0:
  1303.                 memberlist.remove(EntityName)
  1304.  
  1305.             if len(memberlist) > 0:
  1306.                 memberlist.sort(ChooseFighter)
  1307.                 member = Bladex.GetEntity (memberlist[0])
  1308.                 if member and member.Life > 0:
  1309.                     member.CombatDistFlag = 0    # move in
  1310.                     member.Data.group_fighter = TRUE
  1311.  
  1312.     def SetGroupLeader(self,EntityName, include_me):
  1313.         me = Bladex.GetEntity(EntityName)
  1314.         if me.CombatGroup:
  1315.             self.SetNoGroupLeader (EntityName)
  1316.             # Can I find someone else to go in close range
  1317.             memberlist = me.GetGroupMembers()
  1318.             if (not include_me) and memberlist.count(EntityName) > 0:
  1319.                 memberlist.remove(EntityName)
  1320.  
  1321.             if len(memberlist) > 0:
  1322.                 memberlist.sort(ChooseLeader)
  1323.                 member = Bladex.GetEntity (memberlist[0])
  1324.                 if member and member.Life>0:
  1325.                     member.Data.group_leader = TRUE
  1326.  
  1327.     def Respond2Thrown(self, EntityName, AttackerName):
  1328.         me = Bladex.GetEntity(EntityName)
  1329.         if AttackerName:
  1330.             enemy=Bladex.GetEntity(me.GetEnemyName())
  1331.             if enemy and not enemy.InsideActionArea(me.ActionAreaMax):
  1332.                 self.LastThrownHurtTime=Bladex.GetTime()
  1333.                 init_pos=me.InitPos
  1334.                 me.InvertedRoute=0 #Just in case
  1335.                 me.GoToJogging=1
  1336.                 if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  1337.                     me.RouteEndedFunc= self.Turn180AndWatch
  1338.             else:
  1339.                 if me.GetActionMode() == ROUTE_WATCH:
  1340.                     #print "FIX?"
  1341.                     Actions.QuickTurnToFaceEntity(EntityName,AttackerName)
  1342.                 else:
  1343.                     print "Respond2Thrown->Bug?"
  1344.  
  1345.  
  1346.     def RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageZone, Shielded):
  1347.         # launch appropriate hurt anim
  1348.         Basic_Funcs.PlayerPerson.RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageZone, Shielded)
  1349.         
  1350.         if AttackerName and AttackerName != 'BWorld' and AttackerName != EntityName:
  1351.             me = Bladex.GetEntity(EntityName)
  1352.             if me and me.Life > 0:
  1353.                 # consider getting furious
  1354.                 chartype = Bladex.GetCharType(me.CharType,me.CharTypeExt)
  1355.                 if me.Life <= CharStats.GetCharMaxLife(me.Kind, me.Level)*0.25 and whrandom.random() < self.ChanceOfFuryOnHurt:
  1356.                     self.GetFurious (EntityName)
  1357.                 # consider attacking attacker back
  1358.                 damage_factor = DamagePoints / (me.Life+DamagePoints)
  1359.                 if damage_factor > me.Data.DamageFactorNone:
  1360.                     # Only if I'm still alive... Death events handled apart
  1361.                     Reference.debugprint(EntityName+": Im being attacked by "+AttackerName)
  1362.                     if AttackerName != me.GetEnemyName():
  1363.                         Reference.debugprint(EntityName+": " + AttackerName +" is not my enemy!" )
  1364.                         attacker = Bladex.GetEntity(AttackerName)
  1365.                         if attacker and (self.AttacksOwnKind or attacker.Kind != me.Kind):
  1366.                             Reference.debugprint(EntityName+": I will attack back")
  1367.                             # Only attack NPCs if not already, otherwise we get multiple scheduled funcs
  1368.                             if (not attacker.Data.NPC) or (not self.AttackingNPC):
  1369.                                 Reference.debugprint("attacker.Data.NPC: "+ `attacker.Data.NPC`+ ", self.AttackingNPC: " + `self.AttackingNPC`)
  1370.                                 # Interrupt whatever we were doing before
  1371.                                 Damage.DropInvalidObjectsOnImpact (EntityName)
  1372.                                 me.Wuea=Reference.WUEA_ENDED
  1373.                                 me.InterruptCombat()
  1374.                                 
  1375.                                 # Set up the new enemy, and start chasing him to be sure
  1376.                                 #print EntityName+": Starting attacking "+attacker.Name+" at time: "+`Bladex.GetTime()`
  1377.                                 me.SetEnemy(attacker)
  1378.                                 me.SetActiveEnemy(attacker)
  1379.                                 me.Chase(attacker, me.ActionAreaMax)
  1380.                                 if me.GetActionMode()==ROUTE_CHASE and self.IsArcher():
  1381.                                     self.Switch2MeleeWeapons(EntityName)
  1382.                                 
  1383.                                 
  1384.                                 #if not me.CanISee(attacker):
  1385.                                 #    me.Wuea=Reference.WUEA_ENDED
  1386.                                 #    me.LaunchAnmType("attack_look",1)
  1387.                                 
  1388.                                 # If its another NPC, we should make the switch from the PC temporary
  1389.                                 if attacker.Data.NPC:
  1390.                                     #pdb.set_trace()
  1391.                                     self.AttackingNPC=TRUE
  1392.                                     Bladex.AddScheduledFunc(Bladex.GetTime() + self.AttackNPCTime, self.StopNPCsAttacking,(EntityName,))
  1393.                                     if me.CombatGroup == attacker.CombatGroup:
  1394.                                         self.LeaveGroup (EntityName)
  1395.                                         self.CheckToJoin (EntityName)
  1396.                                         return
  1397.                     if me.CombatGroup and self.group_fighter and me.Life > 0:    # I am in close range
  1398.                         self.SetGroupFormation (EntityName, TRUE, FALSE)
  1399.  
  1400.  
  1401.     def HitFunc (self, EntityName, WeaponName, Cx, Cy, Cz, DirX, DirY, DirZ,wcx,wcy,wcz,wdx,wdy,wdz):
  1402.         me= Bladex.GetEntity(EntityName)
  1403.         if me and me.Life>0:
  1404.             if not me.InCombat:
  1405.                 
  1406.                 #x= pos[0]-DirX*1000.0
  1407.                 #z= pos[2]-DirZ*1000.0
  1408.                 
  1409.                 weapon= Bladex.GetEntity (WeaponName)
  1410.                 if weapon and weapon.Parent:
  1411.                     if not Actions.IsFacingEntity(EntityName, weapon.Parent):
  1412.                         Actions.QuickTurnToFaceEntity(EntityName, WeaponName)
  1413.                 else:
  1414.                     pos= me.Position
  1415.                     x= pos[0]+(Cx-pos[0])*1000.0
  1416.                     z= pos[2]+(Cz-pos[2])*1000.0
  1417.                     if not Actions.IsFacingPos(EntityName, x, z):
  1418.                         Actions.QuickTurnToFacePos(EntityName, x, z)
  1419.  
  1420.         Basic_Funcs.PlayerPerson.HitFunc (self, EntityName, WeaponName, Cx, Cy, Cz, DirX, DirY, DirZ,wcx,wcy,wcz,wdx,wdy,wdz)
  1421.  
  1422.  
  1423.     #
  1424.     # Standard function for dying
  1425.     #
  1426.  
  1427.         
  1428.     def StdImDead(self,EntityName):
  1429.         global TwinkleObjs
  1430.         Reference.debugprint(EntityName+": I died!")
  1431.         Basic_Funcs.PlayerPerson.PCImDead(self, EntityName)        
  1432.         
  1433.         me = Bladex.GetEntity(EntityName)
  1434.         if me.Life > 0:
  1435.             print EntityName + ': Warning! dead func when Life > 0!'
  1436.  
  1437.         DMusic.InformDead(EntityName)
  1438.         
  1439.         me.RemoveFromList("Listeners")
  1440.         #pdb.set_trace()
  1441.         me.AddAnmEventFunc("UnlinkAll", self.UnlinkAll)
  1442.         if self.Asleep:
  1443.             me.Wuea=Reference.WUEA_ENDED
  1444.             me.LaunchAnmType("sleep_wall_d")
  1445.             Reference.debugprint(EntityName+": Uuurgh! I died in my sleep!")
  1446.  
  1447.         if self.group_leader:
  1448.             memberlist = me.GetGroupMembers()
  1449.             if EntityName in memberlist:
  1450.                 memberlist.remove(EntityName)
  1451.             if len(memberlist) == 1:
  1452.                 # Chance that remaining member gets furious
  1453.                 #pdb.set_trace()
  1454.                 member = Bladex.GetEntity(memberlist[0])
  1455.                 if member and member.Life > 0:
  1456.                     enemy=Bladex.GetEntity(member.GetEnemyName()) 
  1457.                     if member.SQDistance2(enemy) > 3000*3000 or not Actions.IsFacingEntity(enemy.Name, member.Name):
  1458.                         if whrandom.random() < self.ChanceOfFuryOnLeaderDeath:
  1459.                             member.Data.GetFurious (member.Name)
  1460.  
  1461.         self.CheckGoodGroupFormation (EntityName, FALSE)
  1462.         self.CallGroupMemberFunc(EntityName, Combat.GetAngry, FALSE)
  1463.         
  1464.         me.RemoveFromList(me.CombatGroup)
  1465.  
  1466.         csound=Bladex.GetEntity(EntityName+"ContinuosSound")
  1467.         if csound:
  1468.             csound.StopSound()
  1469.             csound.SubscribeToList("Pin")
  1470.  
  1471.  
  1472.         # Drop the weapons if possible
  1473.  
  1474.         try:
  1475.             object = Bladex.GetEntity(me.InvLeft)
  1476.             if me.InvLeft and object and not object.TestHit:
  1477.                 Actions.RemoveFromInventory (me, object,"DropLeftEvent")
  1478.                 object.Alpha=1.0
  1479.                 object.Impulse(0.0, 0.0, 0.0) 
  1480.         except AttributeError: 
  1481.             pdb.set_trace()
  1482.         
  1483.         try:
  1484.             object = Bladex.GetEntity(me.InvRight)
  1485.             if me.InvRight and object and not object.TestHit:
  1486.                 Actions.RemoveFromInventory (me, object,"DropRightEvent")
  1487.                 object.Alpha=1.0
  1488.                 object.Impulse(0.0, 0.0, 0.0) 
  1489.         except AttributeError: 
  1490.             pdb.set_trace()
  1491.             
  1492.         # Drop everything else
  1493.         inv = me.GetInventory()
  1494.         #pdb.set_trace()
  1495.         while inv.nObjects > 0:
  1496.             object_name = inv.GetObject(0)
  1497.             object = Bladex.GetEntity(object_name)
  1498.             if object:
  1499.                 object.Position=me.Position
  1500.                 me.Unlink(object)
  1501.                 inv.RemoveObject(object_name)
  1502.                 object.ExcludeHitFor(me)
  1503.                 if object.Kind in TwinkleObjs:
  1504.                     Bladex.AddScheduledFunc(Bladex.GetTime(), Actions.TakeObject,("Player1",object_name))
  1505.                 else:    
  1506.                     if object.TestHit:
  1507.                         print "WARNING OBJECT "+object.Name+" REMOVED FROM WORLD BECAUSE COLLIDING"
  1508.                         object.RemoveFromWorld()
  1509.                     else:
  1510.                         object.Alpha=1.0
  1511.                         object.Impulse(0.0, 0.0, 0.0)
  1512.  
  1513.         while inv.nWeapons > 0:
  1514.             object_name = inv.GetWeapon(0)
  1515.             object = Bladex.GetEntity(object_name)
  1516.             if object:
  1517.                 object.Position=me.Position
  1518.                 me.Unlink(object)
  1519.                 inv.RemoveWeapon(object_name)
  1520.                 object.ExcludeHitFor(me)
  1521.                 try:
  1522.                     if object.TestHit:
  1523.                         object.RemoveFromWorld()
  1524.                     else:
  1525.                         object.Alpha=1.0
  1526.                         object.Impulse(0.0, 0.0, 0.0) 
  1527.                 except AttributeError:
  1528.                     print "TestHit unsupported for object "+object.Name
  1529.                     pdb.set_trace()
  1530.  
  1531.         while inv.nShields > 0:
  1532.             object_name = inv.GetShield(0)
  1533.             object = Bladex.GetEntity(object_name)
  1534.             if object:
  1535.                 object.Position=me.Position
  1536.                 me.Unlink(object)
  1537.                 inv.RemoveShield(object_name)
  1538.                 object.ExcludeHitFor(me)
  1539.                 if object.TestHit:
  1540.                     object.RemoveFromWorld()
  1541.                 else:
  1542.                     object.Alpha=1.0
  1543.                     object.Impulse(0.0, 0.0, 0.0) 
  1544.         
  1545.         while inv.nQuivers > 0:
  1546.             object_name = inv.GetQuiver(0)
  1547.             object = Bladex.GetEntity(object_name)
  1548.             if object:
  1549.                 object.Position=me.Position
  1550.                 me.Unlink(object)
  1551.                 inv.RemoveQuiver(object_name)
  1552.                 object.ExcludeHitFor(me)
  1553.                 if object.TestHit:
  1554.                     object.RemoveFromWorld()
  1555.                 else:
  1556.                     object.Alpha=1.0
  1557.                     object.Impulse(0.0, 0.0, 0.0) 
  1558.  
  1559.         while inv.nKeys > 0:
  1560.             object_name = inv.GetKey(0)
  1561.             object = Bladex.GetEntity(object_name)
  1562.             if object: 
  1563.                 object.Position=me.Position
  1564.                 me.Unlink(object)
  1565.                 inv.RemoveKey(object_name)
  1566.                 object.ExcludeHitFor(me)
  1567.                 Bladex.AddScheduledFunc(Bladex.GetTime(), Actions.TakeObject,("Player1",object_name))
  1568.                 
  1569.                 char = Bladex.GetEntity("Player1")
  1570.                 new_key_sound.Stop()
  1571.                 new_key_sound.PlayStereo()
  1572.                 #new_key_sound.Play(char.Position[0],char.Position[1],char.Position[2],0);
  1573.                 
  1574.                     
  1575.  
  1576.     #
  1577.     # Standard function for the enemies' death
  1578.     #
  1579.     def StdEnemyDead(self,EntityName):
  1580.         me = Bladex.GetEntity(EntityName)
  1581.         # Check I'm not dead        
  1582.         if me:
  1583.             if me.Life > 0 and (me.GetActionMode()==ROUTE_CHASE or me.InCombat):
  1584.                 me.DelayNoSeenFunc=self.StdDelayNoSeen
  1585.                 if me.Data.imusic_noseen_warp==1:
  1586.                     DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  1587.  
  1588.                 self.InvestigatingSound = FALSE
  1589.                 self.LaunchMyWatch(EntityName)
  1590.                 Reference.debugprint(EntityName+": My enemy is dead.He he ! - py")
  1591.             
  1592.  
  1593.     def GetFurious (self, EntityName):
  1594.         me=Bladex.GetEntity(EntityName)
  1595.         
  1596.         if me and self.Furious == 0:        
  1597.             Reference.debugprint(EntityName + ": Getting Furious")
  1598.             self.Furious = 1
  1599.             me.BlockingPropensity = 0
  1600.  
  1601.             # Save the first attack
  1602.             movelist = me.AttackList
  1603.             first_attack = None
  1604.             for move in movelist:
  1605.                 if move[0]==Combat.ATTACK:
  1606.                     first_attack = move
  1607.                     break
  1608.             me.AttackList=filter(Combat.DoneInFury,me.AttackList)
  1609.             if first_attack:
  1610.                 first_attack[1]=1.00
  1611.                 me.AttackList.insert(0, first_attack)
  1612.  
  1613.             me.CombatDistFlag = 0
  1614.             Damage.DropInvalidObjectsOnImpact (EntityName)
  1615.             me.Wuea=Reference.WUEA_ENDED
  1616.             me.InterruptCombat()
  1617.             me.LaunchAnmType("fury",1)
  1618.             FuryTime=30.0
  1619.             Bladex.AddScheduledFunc(Bladex.GetTime() + FuryTime, self.ResetCombat,(EntityName,))
  1620.  
  1621.     #
  1622.     # Standard function for end of animation
  1623.     # It is set to null when finish!
  1624.     #
  1625.     def StdAnmEnded(self,EntityName):
  1626.         pass
  1627.         Reference.debugprint(EntityName+": Anm ended - py ")
  1628.  
  1629.     #
  1630.     # Standard function for entering close range combat 
  1631.     # Called only when CHASING an enemy !
  1632.     #
  1633.     def StdEnterClose(self,EntityName):
  1634.         Reference.debugprint(EntityName+": I am entering close combat")
  1635.         #pdb.set_trace()        
  1636.         me = Bladex.GetEntity(EntityName)
  1637.         # Check I'm not dead
  1638.         if me and me.Life > 0:
  1639.             self.SetGroupFormation (EntityName, TRUE, FALSE)
  1640.             self.Switch2MeleeWeapons (EntityName)
  1641.         
  1642.                     
  1643.     def Switch2MeleeWeapons(self,EntityName):
  1644.         me = Bladex.GetEntity(EntityName)
  1645.         if me and me.Life > 0 and not me.RangeActive:
  1646.             inv= me.GetInventory()
  1647.             right_type= Reference.GiveObjectFlag(me.InvRight)
  1648.                         
  1649.             # Do we have an item in the hand we can fight with            
  1650.             if inv.HoldingBow or not (right_type== Reference.OBJ_STANDARD or right_type== Reference.OBJ_WEAPON):
  1651.                 # Don't change if the enemy is unreachable
  1652.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  1653.                 if me.AstarState!=ASTAR_NOSOLVED:
  1654.                     me.SwitchTo1H()
  1655.                     weapon_name= inv.GetSelectedWeapon()
  1656.                     if weapon_name and (weapon_name != me.InvRight and weapon_name != me.InvLeft):
  1657.                         # Launch the swap weapons animation
  1658.                         out= ScorerActions.CB_WeaponOutX(EntityName,0)
  1659.                         if not out:
  1660.                             me.AnmEndedFunc= ScorerActions.CB_WeaponOutX
  1661.                         Bladex.AddScheduledFunc(Bladex.GetTime()+2.0, self.Switch2MeleeWeapons,(EntityName,),EntityName+"ReSwitch2MeleeWeapons")
  1662.                 
  1663.                     Actions.EndBowMode(EntityName)
  1664.             
  1665.     def WeaponsOut(self,EntityName):
  1666.         me= Bladex.GetEntity(EntityName)
  1667.         if me.Life > 0:
  1668.             inv= me.GetInventory()
  1669.             if inv.HasBow:                
  1670.                 # Put quiver on back
  1671.                 des_quiver_name=inv.GetSelectedQuiver()
  1672.                 if des_quiver_name:
  1673.                     inv.LinkBack(des_quiver_name)
  1674.                     
  1675.                     # Put arrow in right
  1676.                     inv.LinkRightHand("None")
  1677.                     quiver=    Bladex.GetEntity(des_quiver_name)
  1678.                     if quiver and quiver.Data.NumberOfArrows() > 0:
  1679.                         arrow= quiver.Data.GiveArrow ()
  1680.                         inv.LinkRightHand(arrow.Name)
  1681.                                 
  1682.                         # Put bow in left
  1683.                         bow= inv.GetBow()
  1684.                         inv.LinkLeftHand(bow)
  1685.                         
  1686.                         return
  1687.                 
  1688.                 print "Enemy starting with bow, but without quiver/arrows"
  1689.             
  1690.             # Put sword in right
  1691.             if inv.nWeapons>0 and not me.InvRight:
  1692.                 weapon_name= inv.GetSelectedWeapon()
  1693.                 if not weapon_name:
  1694.                     weapon_name= inv.GetWeapon(0)
  1695.                 inv.LinkRightHand("None")
  1696.                 inv.LinkRightHand(weapon_name)
  1697.             
  1698.             # Put shield in left
  1699.             if inv.nShields>0 and not me.InvLeft:
  1700.                 shield_name= inv.GetSelectedShield()
  1701.                 if not shield_name:
  1702.                     shield_name= inv.GetShield(0)
  1703.                 inv.LinkLeftHand("None")
  1704.                 inv.LinkLeftHand(weapon_name)
  1705.     
  1706.         
  1707.     #
  1708.     # Standard function for entering large range combat 
  1709.     # Called only when CHASING an enemy !
  1710.     #                 
  1711.     def StdEnterLarge(self,EntityName):
  1712.         me = Bladex.GetEntity(EntityName)
  1713.         # Check I'm not dead        
  1714.         Reference.debugprint(EntityName + ": Im entering large area!")
  1715.         if me.Life > 0 and not me.MeleeActive:
  1716.             inv= me.GetInventory()
  1717.             if inv.HasBow:
  1718.                 left_type= Reference.GiveObjectFlag(me.InvLeft)
  1719.                 if left_type != Reference.OBJ_BOW:
  1720.                     me.SwitchToBow()
  1721.                     if inv.GetSelectedWeapon() != me.InvRight and inv.GetSelectedWeapon() != me.InvLeft:
  1722.                         # Launch the swap weapons animation
  1723.                         out= ScorerActions.CB_WeaponOutX(EntityName,0)
  1724.                         if not out:
  1725.                             me.AnmEndedFunc= ScorerActions.CB_WeaponOutX
  1726.                         Bladex.AddScheduledFunc(Bladex.GetTime()+2.0, self.StdEnterLarge,(EntityName,),EntityName+"ReStdEnterLarge")
  1727.  
  1728.     #
  1729.     # Standard function for entering PRIMARY AA
  1730.     #
  1731.     def StdEnterPrimaryAA(self,EntityName):
  1732.         me = Bladex.GetEntity(EntityName)
  1733.         Reference.debugprint(EntityName + ": Im entering primary area!")
  1734.         # Check I'm not dead
  1735.         if me.Life > 0:
  1736.             #NO -> Only called onlled once this function(...) !!!
  1737.             #if me.InvertedRoute==1 and not me.Will1aaTo2aa:
  1738.             if me.InvertedRoute==1:
  1739.                 self.LaunchMyWatch (EntityName)
  1740.                 me.LastTimeSeen=Bladex.GetTime()
  1741.             me.InvertedRoute=0 #Por si acaso
  1742.         
  1743.     
  1744.     #
  1745.     # Standard function for entering SECONDARY AA
  1746.     #                 
  1747.     def StdEnterSecondaryAA(self,EntityName):
  1748.         Reference.debugprint(EntityName + ": Im entering secondary area!")
  1749.         #print "StdEnterSecondaryAA"
  1750.         pass
  1751.             
  1752.  
  1753.     #
  1754.     # Standard function for when another character sees his enemy 
  1755.     # (...)
  1756.     #
  1757.     def StdCharSeeingEnemy(self,EntityName,EntityName2):    
  1758.         me = Bladex.GetEntity(EntityName)
  1759.         ally=Bladex.GetEntity(EntityName2)
  1760.  
  1761.         if me.CombatGroup==ally.CombatGroup:
  1762.             pass #Bob's grouping suff will do it
  1763.         # Check I'm not dead
  1764.         if me.Life > 0:
  1765.             #Reference.debugprint(EntityName + ": Im in StdCharSeeingEnemy with Char being " + EntityName2)
  1766.             
  1767.             if ally and me.CanISee(ally) and me.GetActionMode()<>ROUTE_CHASE:
  1768.                 if ally.GetActionMode()==ROUTE_CHASE and me.GetActionMode()<>ROUTE_CHASE:
  1769.                     me.SeeFunc(EntityName)
  1770.                 if ally.GetActionMode()==ROUTE_SINGLE and ally.Data.InvestigatingSound:
  1771.                     #Volume set to 1 , so he┤ll always hear it
  1772.                     self.StdHearFunc(EntityName,ally.Data.InvestigatingSoundName,ally.Data.InvestigatingSoundX,ally.Data.InvestigatingSoundY,ally.Data.InvestigatingSoundZ,1.0)
  1773.                     
  1774.             else:
  1775.                 pass
  1776.                 #Reference.debugprint(EntityName + ": I cannot see ally")
  1777.  
  1778.     #
  1779.     # Standard function for enggling on and off with an enemy
  1780.     # (...)
  1781.     #
  1782.     def StdToggleCombat(self,EntityName):
  1783.         import DMusic
  1784.         if self.NPC==1:
  1785.             DMusic.notifyCombat(EntityName)
  1786.  
  1787.     # Functions for loading and saving state
  1788.     def __save_core_funcs__(self):
  1789.         me = Bladex.GetEntity(self.Name)
  1790.         if not me:
  1791.             print "__save_core_funcs__() Warning: trying to save a non existent entity",self.Name
  1792.             return
  1793.  
  1794.         core_funcs = []
  1795.         j = 0
  1796.         funcs=[ ("SeeFunc",               self.StdSeeTheEnemy),
  1797.                 ("HearFunc",              self.StdHearFunc),
  1798.                 ("DelayNoSeenFunc",       self.StdDelayNoSeen),
  1799.                 ("NoAllowedAreaFunc",     self.StdNoAllowedArea),
  1800.                 ("EnemyNoAllowedAreaFunc",self.StdEnemyNoAllowedArea),
  1801.                 ("ImHurtFunc",            self.StdImHurt),
  1802.                 ("ImDeadFunc",            self.StdImDead),
  1803.                 ("EnemyDeadFunc",         self.StdEnemyDead),
  1804.                 ("AnmEndedFunc",          self.StdAnmEnded),
  1805.                 ("EnterCloseFunc",        self.StdEnterClose),
  1806.                 ("EnterLargeFunc",        self.StdEnterLarge),
  1807.                 ("EnterPrimaryAAFunc",    self.StdEnterPrimaryAA),
  1808.                 ("EnterSecondaryAAFunc",  self.StdEnterSecondaryAA),
  1809.                 ("CharSeeingEnemyFunc",   self.StdCharSeeingEnemy),
  1810.                 ("ToggleCombatFunc",      self.StdToggleCombat),
  1811.                 ("DamageFunc",            Damage.CalculateDamage),
  1812.                 ]
  1813.  
  1814.         for i in funcs:
  1815.             exec('f = me.'+i[0])
  1816.             if (i[1] <> f):
  1817.                 print "Save Core Func para",me.Name," callback ",i[0]," funcion ", f
  1818.                 core_funcs.append((j,GameStateAux.SaveFunctionAux(f)))
  1819.             j = j + 1
  1820.  
  1821.         return(core_funcs)
  1822.  
  1823.     def __load_core_funcs__(self,param):
  1824.  
  1825.  
  1826.         me = Bladex.GetEntity(self.Name)
  1827.         if not me:
  1828.             print "__load_core_funcs__ -> Warning, trying to get a non existent entity",self.Name
  1829.             return
  1830.         
  1831.         funcs=[ "SeeFunc",
  1832.                 "HearFunc",
  1833.                 "DelayNoSeenFunc",
  1834.                 "NoAllowedAreaFunc",
  1835.                 "EnemyNoAllowedAreaFunc",
  1836.                 "ImHurtFunc",
  1837.                 "ImDeadFunc",
  1838.                 "EnemyDeadFunc",
  1839.                 "AnmEndedFunc",
  1840.                 "EnterCloseFunc",
  1841.                 "EnterLargeFunc",
  1842.                 "EnterPrimaryAAFunc",
  1843.                 "EnterSecondaryAAFunc",
  1844.                 "CharSeeingEnemyFunc",
  1845.                 "ToggleCombatFunc",
  1846.                 "DamageFunc",
  1847.                 ]
  1848.  
  1849.         for i in param:
  1850.             try:
  1851.                 GameStateAux.LoadFunctionAux(i[1],me,funcs[i[0]])
  1852.                 #print "Load Core Func ",i[1]," para ",me.Name," funcion ",funcs[i[0]]
  1853.             except Exception,exc:
  1854.                 print "Exception in __load_core_funcs__",exc,i
  1855.  
  1856.     def __getstate__(self):
  1857.         # Tiene que devolver c≤mo poder guardar el estado de la clase
  1858.         PlayerPerson_state=Basic_Funcs.PlayerPerson.__getstate__(self)
  1859.         if(PlayerPerson_state[0]!=1):
  1860.             print "ERROR: NPCPerson.__getstate__(): Base class version differs."
  1861.             # Throw?
  1862.             return playerperson_state
  1863.         me=Bladex.GetEntity(self.Name)
  1864.         PlayerPerson_state[1]["NPCPerson"]=(self.InvestigatingSound,
  1865.                                       self.SoundPriorities,
  1866.                                       self.Asleep,
  1867.                                       self.SleepYOffset,
  1868.                                       self.group_fighter,
  1869.                                       self.group_leader,
  1870.                                       self.AttackingNPC,
  1871.                                       self.last_insulting_time_1AA,
  1872.                                       self.LastThrownHurtTime,
  1873.                                       self.AttacksOwnKind,
  1874.                                       self.AttackNPCTime,
  1875.                                       self.Angry,
  1876.                                       self.Furious,
  1877.                                       self.ChanceOfFuryOnHurt,
  1878.                                       self.ChanceOfFuryOnLeaderDeath,
  1879.                                       self.ImpatientAttackTime,
  1880.                                       self.imusic_noseen_warp,
  1881.                                       self.DelayNoSeenFuncMusicBackUp,
  1882.                                       me.CombatGroup,
  1883.                                       self.__save_core_funcs__()
  1884.                                       )
  1885.         return PlayerPerson_state
  1886.  
  1887.     def __setstate__(self,parm):
  1888.         # Toma como parßmetro lo que devuelve __getstate__() y debe recrear la clase
  1889.         Basic_Funcs.PlayerPerson.__setstate__(self,parm)
  1890.  
  1891.         me=Bladex.GetEntity(self.Name)
  1892.         #_________________________________________#
  1893.         # Set up the core functions               #
  1894.         #_________________________________________#
  1895.         me.SeeFunc=self.StdSeeTheEnemy
  1896.         me.HearFunc=self.StdHearFunc
  1897.         me.DelayNoSeenFunc=self.StdDelayNoSeen
  1898.         me.NoAllowedAreaFunc=self.StdNoAllowedArea
  1899.         me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  1900.         me.ImHurtFunc=self.StdImHurt
  1901.         me.ImDeadFunc=self.StdImDead
  1902.         me.EnemyDeadFunc=self.StdEnemyDead
  1903.         me.AnmEndedFunc=self.StdAnmEnded
  1904.         me.EnterCloseFunc=self.StdEnterClose
  1905.         me.EnterLargeFunc=self.StdEnterLarge
  1906.         me.EnterPrimaryAAFunc=self.StdEnterPrimaryAA
  1907.         me.EnterSecondaryAAFunc=self.StdEnterSecondaryAA
  1908.         me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy
  1909.         me.ToggleCombatFunc=self.StdToggleCombat
  1910.  
  1911.         version=parm[0]
  1912.         if version==1:
  1913.             parms=parm[1]["NPCPerson"]
  1914.             self.InvestigatingSound=parms[0]
  1915.             self.SoundPriorities=parms[1]
  1916.             self.Asleep=parms[2]
  1917.             self.SleepYOffset=parms[3]
  1918.             self.group_fighter=parms[4]
  1919.             self.group_leader=parms[5]
  1920.             self.AttackingNPC=parms[6]
  1921.             self.last_insulting_time_1AA=parms[7]
  1922.             self.LastThrownHurtTime=parms[8]
  1923.             self.AttacksOwnKind=parms[9]
  1924.             self.AttackNPCTime=parms[10]
  1925.             self.Angry=parms[11]
  1926.             self.Furious=parms[12]
  1927.             self.ChanceOfFuryOnHurt=parms[13]
  1928.             self.ChanceOfFuryOnLeaderDeath=parms[14]
  1929.             self.ImpatientAttackTime=parms[15]
  1930.             self.imusic_noseen_warp=parms[16]
  1931.             self.DelayNoSeenFuncMusicBackUp=parms[17]
  1932.             me.CombatGroup=parms[18]
  1933.             self.__load_core_funcs__(parms[19])
  1934.         self.ResetCombat(self.Name)
  1935.         AddMyWatchAnims(self.Name)
  1936.         me=Bladex.GetEntity(self.Name)
  1937.  
  1938.         #Revisar estas 3, deberφan estar con las propiedades de la entidad.
  1939.         #me.BlockingPropensity = 0.5
  1940.         #me.AttackList = []
  1941.         me.CombatDistFlag = not self.group_fighter
  1942.         self.NoFXOnHit= FALSE
  1943.         self.WeaponsOut(self.Name)
  1944.  
  1945.  
  1946. def AddMyWatchAnims(EntityName):
  1947.     Reference.debugprint(EntityName + " adding WatchAnims")
  1948.     me = Bladex.GetEntity(EntityName)
  1949.     #me.AddWatchAnim("PATROL_LOOK_D")
  1950.     #me.AddWatchAnim("PATROL_LOOK_U")
  1951.     #me.AddWatchAnim("PATROL_LOOK_R")
  1952.     #me.AddWatchAnim("PATROL_LOOK_L")
  1953.  
  1954.  
  1955. ##############################################################
  1956. #    Clase base para caracteres estupidos, en principio       #
  1957. ##############################################################
  1958.  
  1959. #Nota: Se ira ampliando a medida que haga falta
  1960.  
  1961. class StupidNPCPerson (Basic_Funcs.PlayerPerson):
  1962.  
  1963.     InvestigatingSound = FALSE
  1964.     SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  1965.  
  1966.     def __init__(self, me):
  1967.         Basic_Funcs.PlayerPerson.__init__(self, me)
  1968.  
  1969.         self.SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  1970.         ###############################
  1971.         #  Record some personal data  #
  1972.         ###############################
  1973.  
  1974.         self.NPC = 1
  1975.  
  1976. #        self.Asleep = FALSE
  1977. #        self.SleepYOffset = 1100.0        # this may need adjusting for non-knight chars
  1978.  
  1979.         #####################
  1980.         #  Initialise core  #
  1981.         #####################
  1982.  
  1983.         me.SubscribeToList("Listeners")
  1984.         me.Deaf = 0
  1985.  
  1986.     def RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageZone, Shielded):
  1987.         pass
  1988.  
  1989.         ###############################
  1990.         #  Set up the core functions  #
  1991.         ###############################
  1992.  
  1993. #        me.SeeFunc=self.StdSeeTheEnemy
  1994. #        me.HearFunc=self.StdHearFunc
  1995. #        me.DelayNoSeenFunc=self.StdDelayNoSeen
  1996. #        me.NoAllowedAreaFunc=self.StdNoAllowedArea
  1997. #        me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  1998. #        me.ImHurtFunc=self.StdImHurt
  1999. #        me.ImDeadFunc=self.StdImDead
  2000. #        me.EnemyDeadFunc=self.StdEnemyDead
  2001. #        me.AnmEndedFunc=self.StdAnmEnded
  2002. #        me.EnterCloseFunc=self.StdEnterClose
  2003. #        me.EnterLargeFunc=self.StdEnterLarge
  2004. #        me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy
  2005.  
  2006.  
  2007.     ##########################
  2008.     #  Define our functions  #
  2009.     ##########################
  2010.