Table of Contents
- A.1.
<res>
/scripts/cell/RandomNavigator.py - A.2.
<res>
/scripts/client/RandomNavigator.py - A.3.
<res>
/scripts/base/RandomNavigator.py - A.4.
<res>
/scripts/editor/RandomNavigator.py - A.5.
<res>
/scripts/entity_defs/RandomNavigator.def - A.6.
<res>
/scripts/base/ElPolloDiablo.py - A.7.
<res>
/scripts/client/ElPolloDiablo.py - A.8.
<res>
/scripts/entity_defs/ElPolloDiablo.def - A.9.
<res>
/scripts/cell/ElPolloDiablo.py - Before - A.10.
<res>
/scripts/cell/ElPolloDiablo.py - After
import BigWorld import math import random import Math class RandomNavigator( BigWorld.Entity ): TIMER_WAITING_FOR_NAVMESH = 1 #--------------------------------------------------------------------- # Constructor. #--------------------------------------------------------------------- def __init__( self ): BigWorld.Entity .__init__( self ) self.destination = self.position self.addTimer( 5.0, 0, RandomNavigator.TIMER_WAITING_FOR_NAVMESH ) #--------------------------------------------------------------------- # This method is called when a timer expires. #--------------------------------------------------------------------- def onTimer(self, timerId, userId): if userId == RandomNavigator.TIMER_WAITING_FOR_NAVMESH: if self.canNavigateTo( self.position ) == None: self.addTimer( 5.0, 0, RandomNavigator.TIMER_WAITING_FOR_NAVMESH ) else: self.navigateStep( self.destination, 5.0, 10.0 ) #--------------------------------------------------------------------- # This method is called when we've finished moving to a point. #--------------------------------------------------------------------- def onMove(self, controllerId, userId): if ( self.position - self.destination ).length > 0.1: self.navigateStep( self.destination, 5.0, 10.0 ) else: self.destination = None while self.destination == None: randomDestination = ( self.position.x + random.randrange(-400, 400, 1.0), self.position.y, self.position.z + random.randrange(-400, 400, 1.0) ) self.destination = self.canNavigateTo( randomDestination ) self.navigateStep( self.destination, 5.0, 10.0 ) # RandomNavigator.py
import math import BigWorld from keys import * # -------------------------------------------------------------------------- # Section: class RandomNavigator # -------------------------------------------------------------------------- class RandomNavigator( BigWorld.Entity ): stdModel = 'characters/avatars/base/base.model' def __init__( self ): BigWorld.Entity.__init__( self ) def prerequisites( self ): return [ RandomNavigator.stdModel ] def enterWorld( self ): self.model = BigWorld.Model( RandomNavigator.stdModel ) BigWorld.addShadowEntity( self ) self.targetCaps = [ CAP_CAN_HIT , CAP_CAN_USE ] self.filter = BigWorld.AvatarDropFilter() def leaveWorld( self ): BigWorld.delShadowEntity( self ) self.model = None def use( self ): pass #RandomNavigator.py
import FantasyDemo # -------------------------------------------------------------------------- # Section: class RandomNavigator # -------------------------------------------------------------------------- class RandomNavigator( FantasyDemo.Base ): def __init__( self ): FantasyDemo.Base.__init__( self ) # RandomNavigator.py
class RandomNavigator: def modelName( self, props ): return 'characters/avatars/base/base.model' # RandomNavigator.py
<root> <Volatile> <position/> <yaw/> </Volatile> <Properties> <destination> <Type> PYTHON </Type> <Flags> CELL_PRIVATE </Flags> </destination> </Properties> <ClientMethods> </ClientMethods> <CellMethods> </CellMethods> </root>
import FantasyDemo # ------------------------------------------------------------------- # Section: class ElPolloDiablo # ------------------------------------------------------------------- class ElPolloDiablo( FantasyDemo.Base ): pass # ElPolloDiablo.py
import BigWorld MODEL = "characters/npc/chicken/chicken.model" # ------------------------------------------------------------------- # Class ElPolloDiablo: # # ElPolloDiablo follows an entity, or wanders between two patrol nodes # ------------------------------------------------------------------- class ElPolloDiablo(BigWorld.Entity): # ----------------------------------------------------------------- # Method: __init__ # Description: # - Defines all variables used by the entity. This includes # setting variables to None. # - Does not call any of the accessor methods. Any variables set are # for the purposes of stability. # ------------------------------------------------------------------ def __init__( self ): BigWorld.Entity.__init__( self ) self.filter = BigWorld.AvatarDropFilter() self.model = None # ------------------------------------------------------------------ # Method: prerequisites # Description: # - Return a list of the resources that we want loaded in the background # for us before onEnterWorld() is called. # ------------------------------------------------------------------ def prerequisites( self ): return [ MODEL ] # ------------------------------------------------------------------ # Method: onEnterWorld # Description: # - Creates a model for the ElPolloDiablo. # ------------------------------------------------------------------ def onEnterWorld( self, prereqs ): self.model = prereqs[ MODEL ] self.model.scale = (4.0, 4.0, 4.0) # ------------------------------------------------------------------ # This method is called when the entity leaves the world # ------------------------------------------------------------------ def onLeaveWorld( self ): self.model = None # ------------------------------------------------------------------ # Method: name # Description: # - Part of the entity interface: This allows the client to get a string # name for the entity. # ------------------------------------------------------------------ def name( self ): return "El Pollo Diablo" #ElPolloDiablo.py
<root> <Volatile> <position/> <yaw/> </Volatile> <Implements> <Interface> BaseAndCell </Interface> </Implements> <Properties> <!-- 0 is wander, 1 is follow targetID --> <mode> <Type> INT32 </Type> <Flags> CELL_PRIVATE </Flags> <Persistent> false </Persistent> <Default> 0 </Default> </mode> <targetID> <Type> OBJECT_ID </Type> <Flags> CELL_PRIVATE </Flags> <Persistent> false </Persistent> </targetID> <nextNode> <Type> PATROL_NODE </Type> <Flags> CELL_PRIVATE </Flags> <Persistent> false </Persistent> </nextNode> <prevNode> <Type> PATROL_NODE </Type> <Flags> CELL_PRIVATE </Flags> <Persistent> false </Persistent> </prevNode> </Properties> <ClientMethods> </ClientMethods> <CellMethods> <startFollow> <Args> <id> OBJECT_ID </id> <!-- EntityID --> </Args> </startFollow> <stopFollow> </stopFollow> </CellMethods> <BaseMethods> </BaseMethods> </root>
"This module implements the ElPolloDiablo entity." # BigWorld Modules import BigWorld # Python modules import random import math #todo: replace this with math module def distance(v1, v2): "Returns the distance between two 3d vectors" x = v2[0] - v1[0] z = v2[2] - v1[2] #ignore y value due to the current 13k hack return math.sqrt(x * x + z * z) # ---------------------------------------------------------------------------- # Section: class ElPolloDiablo # ---------------------------------------------------------------------------- class ElPolloDiablo( BigWorld.Entity ): "An ElPolloDiablo entity." PATROL_MODE = 0 FOLLOW_MODE = 1 VELOCITY = 20 PATROL_DISTANCE = 2 FOLLOW_DISTANCE = 10 FOLLOW_ANGLE = math.pi #------------------------------------------------------------------------ # Constructor #------------------------------------------------------------------------ def __init__( self ): BigWorld.Entity.__init__( self ) # random yaw yaw = random.uniform(-math.pi, math.pi) self.direction = (0.0, 0.0, yaw) if self.mode == ElPolloDiablo.PATROL_MODE: self.stopFollow() else: self.startFollow( self.targetID ) def onTimer( self, controllerID, userData ): self.think() def startFollow( self, targetID ): self.mode = ElPolloDiablo.FOLLOW_MODE self.targetID = targetID self.cancel( "Movement" ) self.think() def stopFollow( self ): self.mode = ElPolloDiablo.PATROL_MODE self.nextNode = None self.cancel( "Movement" ) self.think() def think( self ): if self.mode == ElPolloDiablo.PATROL_MODE: self.patrol() else: self.follow() # Patrol brain def patrol( self ): # If we haven't got any nodes, find a pair if self.nextNode is None: self.setupNodes() if self.nextNode is None: # If we can't find a pair of nodes, wait 5 seconds and try again self.cancel( "Movement" ) self.addTimer( 5 ) return # If we've arrived, turn around if self.closeEnoughToNode(): self.swapNodes() # Navigate to slightly closer than self.closeEnoughToNode() self.navigate( self.nextNode.position, ElPolloDiablo.VELOCITY, True, 500, 0.5, ElPolloDiablo.PATROL_DISTANCE * 0.8 ) def closeEnoughToNode( self ): target = self.nextNode return distance( self.position, target.position ) <= ElPolloDiablo.PATROL_DISTANCE def setupNodes( self ): self.prevNode = None self.nextNode = None closest = None dist = 500 for i in BigWorld.userDataObjects.values(): if i.__class__.__name__ != "PatrolNode" or len(i.patrolLinks) == 0: continue if distance( self.position, i.position ) < dist: closest = i dist = distance( self.position, i.position ) if closest is not None: after = closest.patrolLinks[ 0 ] while distance( closest.position, after.position ) < ElPolloDiablo.PATROL_DISTANCE * 3: after = after.patrolLinks[ 0 ] if after is None or after.uuid == closest.uuid: after = None break if after is not None: self.prevNode = closest self.nextNode = after def swapNodes( self ): temp = self.nextNode self.nextNode = self.prevNode self.prevNode = temp def onNavigate( self, controllerID, userData ): # Arrived. Turn around. self.swapNodes() self.think() def onNavigateFailed( self, controllerID, userData ): # Can't get there. Turn around self.swapNodes() self.think() # Follow brain def follow( self ): # If self.targetID doesn't exist, switch to patrol mode if not BigWorld.entities.has_key( self.targetID ): self.stopFollow() return # If target isn't in this space, switch to patrol mode target = BigWorld.entities[ self.targetID ] if target.spaceID != self.spaceID: self.stopFollow() return # If we've arrived, wait here for target to move away if self.closeEnoughToTarget(): self.cancel( "Movement" ) self.addTimer( 5 ) return # Follow our target target = BigWorld.entities[ self.targetID ] try: self.navigateFollow( target, ElPolloDiablo.FOLLOW_ANGLE, ElPolloDiablo.FOLLOW_DISTANCE, ElPolloDiablo.VELOCITY, 500, 500, True, 0.5 ) except ValueError, e: # No path found self.cancel( "Movement" ) self.addTimer( 5 ) def closeEnoughToTarget( self ): target = BigWorld.entities[ self.targetID ] return distance( self.position, target.position ) <= ElPolloDiablo.FOLLOW_DISTANCE def onMove( self, controllerID, userData ): self.think() # ElPolloDiablo.py
"This module implements the ElPolloDiablo entity." # BigWorld Modules import BigWorld # Python modules import random import math #todo: replace this with math module def distance(v1, v2): "Returns the distance between two 3d vectors" x = v2[0] - v1[0] z = v2[2] - v1[2] #ignore y value due to the current 13k hack return math.sqrt(x * x + z * z) # ---------------------------------------------------------------------------- # Section: class ElPolloDiablo # ---------------------------------------------------------------------------- class ElPolloDiablo( BigWorld.Entity ): "An ElPolloDiablo entity." PATROL_MODE = 0 FOLLOW_MODE = 1 VELOCITY = 20 PATROL_DISTANCE = 2 FOLLOW_DISTANCE = 10 FOLLOW_ANGLE = math.pi #------------------------------------------------------------------------ # Constructor #------------------------------------------------------------------------ def __init__( self ): BigWorld.Entity.__init__( self ) # random yaw yaw = random.uniform(-math.pi, math.pi) self.direction = (0.0, 0.0, yaw) if self.mode == ElPolloDiablo.PATROL_MODE: self.stopFollow() else: self.startFollow( self.targetID ) def onTimer( self, controllerID, userData ): self.think() def startFollow( self, targetID ): self.mode = ElPolloDiablo.FOLLOW_MODE self.targetID = targetID self.cancel( "Movement" ) self.think() def stopFollow( self ): self.mode = ElPolloDiablo.PATROL_MODE self.nextNode = None self.cancel( "Movement" ) self.think() def think( self ): if self.mode == ElPolloDiablo.PATROL_MODE: self.patrol() else: self.follow() # Patrol brain def patrol( self ): # If we haven't got any nodes, find a pair if self.nextNode is None: self.setupNodes() if self.nextNode is None: # If we can't find a pair of nodes, wait 5 seconds and try again self.cancel( "Movement" ) self.addTimer( 5 ) return # If we've arrived, turn around if self.closeEnoughToNode(): self.swapNodes() # Navigate towards self.nextNode.position dest = self.canNavigateTo( self.nextNode.position, 500, 0.5 ) if dest is None: # No path found self.cancel( "Movement" ) self.addTimer( 5 ) return self.navigateStep( dest, ElPolloDiablo.VELOCITY, 500, 500, True, 0.5 ) def closeEnoughToNode( self ): target = self.nextNode return distance( self.position, target.position ) <= ElPolloDiablo.PATROL_DISTANCE def setupNodes( self ): self.prevNode = None self.nextNode = None closest = None dist = 500 for i in BigWorld.userDataObjects.values(): if i.__class__.__name__ != "PatrolNode" or len(i.patrolLinks) == 0: continue if distance( self.position, i.position ) < dist: closest = i dist = distance( self.position, i.position ) if closest is not None: after = closest.patrolLinks[ 0 ] while distance( closest.position, after.position ) < ElPolloDiablo.PATROL_DISTANCE * 3: after = after.patrolLinks[ 0 ] if after is None or after.uuid == closest.uuid: after = None break if after is not None: self.prevNode = closest self.nextNode = after def swapNodes( self ): temp = self.nextNode self.nextNode = self.prevNode self.prevNode = temp def onMoveFailure( self, controllerID, userData ): # Can't get there. Turn around self.swapNodes() self.think() # Follow brain def follow( self ): # If self.targetID doesn't exist, switch to patrol mode if not BigWorld.entities.has_key( self.targetID ): self.stopFollow() return # If target isn't in this space, switch to patrol mode target = BigWorld.entities[ self.targetID ] if target.spaceID != self.spaceID: self.stopFollow() return # If we've arrived, wait here for target to move away if self.closeEnoughToTarget(): self.cancel( "Movement" ) self.addTimer( 5 ) return # Follow our target yaw = target.yaw + ElPolloDiablo.FOLLOW_ANGLE offset = ( ElPolloDiablo.FOLLOW_DISTANCE * math.sin( yaw ), 0, ElPolloDiablo.FOLLOW_DISTANCE * math.cos( yaw ) ) dest = self.canNavigateTo( target.position + offset, 500, 0.5 ) if dest is None: # No path found self.cancel( "Movement" ) self.addTimer( 5 ) return self.navigateStep( dest, ElPolloDiablo.VELOCITY, 500, 500, True, 0.5 ) def closeEnoughToTarget( self ): target = BigWorld.entities[ self.targetID ] return distance( self.position, target.position ) <= ElPolloDiablo.FOLLOW_DISTANCE def onMove( self, controllerID, userData ): self.think() # ElPolloDiablo.py