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.pyimport 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.pyimport 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
