class Creature(object): def __init__(self): self.nodepath = NodePath(repr(self)) node = self.nodepath.attachNewNode(CARD_MAKER.generate()) node.setTexture(self.texture) node.setTwoSided(True) node.setTransparency(True) self.nodepath.setBillboardPointEye() self.pos = None self.cur_path = [] #TODO: how to handle creatures actions? self.speed = 4 self.action = random.randint(0, self.speed) def goto(self, pos, asteroid): self.cur_path = find_path(self.pos, pos, asteroid)
class FishLure(NodePath): def __init__(self, gameObject, type): NodePath.__init__(self, "FishingLure_%s" % type) self.gameObject = gameObject self.type = type self.initLureModel() if FishingGlobals.wantDebugCollisionVisuals: self.initCollision() self.initLureHelpText() self.setLightOff() def initLureModel(self): self.lureModel = NodePath("lure") self.currentLureType = "regular" self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[self.currentLureType] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[self.currentLureType]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) self.mainGui = loader.loadModel("models/gui/gui_main") def initCollision(self): self.lureCollisionVisual = loader.loadModel("models/ammunition/cannonball") self.lureCollisionVisual.setTransparency(1) self.lureCollisionVisual.setColor(0.0, 0.0, 1.0, 0.29999999999999999) self.lureCollisionVisual.setScale(self.lureAttractRadius) self.lureCollisionVisual.reparentTo(self) self.lureCollisionVisual.hide() def initLureHelpText(self): self.helpTextNode = TextNode("fishBitingIcon") self.helpTextNodePath = NodePath(self.helpTextNode) self.helpTextNodePath.setPos(0.0, 0.0, 0.69999999999999996) self.helpTextNode.setText(" ") self.helpTextNode.setAlign(TextNode.ACenter) self.helpTextNode.setFont(PiratesGlobals.getPirateFont()) self.helpTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.helpTextNodePath.reparentTo(self) self.helpTextNodePath.setBillboardPointEye() self.helpTextNodePath.setBin("fishingGame", 10) self.helpTextNodePath.hide() def enableLureGlow(self, glowType): self.lureGlow = LureGlow.getEffect() if self.lureGlow: if self.gameObject.fishManager.activeFish is not None: self.lureGlow.reparentTo(self.gameObject.fishManager.activeFish.mouthJoint) else: self.lureGlow.reparentTo(self) self.lureGlow.effectColor = _glowColors[glowType] self.lureGlow.setShaderOff() self.lureGlow.setBin("fishingGame", 5) self.lureGlow.play() def showHelpText(self, textToShow): taskMgr.remove(self.gameObject.distributedFishingSpot.uniqueName("ClearLureText")) if textToShow is None: self.helpTextNode.setText(" ") self.helpTextNodePath.hide() elif self.gameObject.fishManager.activeFish is not None: self.helpTextNodePath.setScale( FishingGlobals.fishSizeToHelpTextScale[self.gameObject.fishManager.activeFish.myData["size"]] ) else: self.helpTextNodePath.setScale(1.0) self.helpTextNode.setText(textToShow) self.helpTextNodePath.show() taskMgr.doMethodLater( FishingGlobals.lureHelpTextDuration, self.showHelpText, name=self.gameObject.distributedFishingSpot.uniqueName("ClearLureText"), extraArgs=[None], ) def setLureType(self, type): self.currentLureType = type if type == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) elif type == "regular": self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[type] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) elif type == "legendary": self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[type] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) def showCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.show() def hideCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.hide() def requestPitch(self, fish): offset = fish.getPos() - self.getPos() if fish.getX() < self.getX(): return math.degrees(math.atan2(offset.getZ(), -offset.getX())) else: return math.degrees(math.atan2(-offset.getZ(), offset.getX())) def resetLureModel(self): self.lureModel.reparentTo(self) self.lureModel.show() self.lureModel.setPosHpr(0, 0, 0, 0, 0, 0.0) if self.currentLureType == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) else: self.gameObject.gui.setTackleBoxPulse(False) def destroy(self): self.lureModel.removeNode() self.removeNode()
class Translation( Base ): def __init__( self, *args, **kwargs ): Base.__init__( self, *args, **kwargs ) # Create x, y, z and camera normal axes self.axes.append( self.CreateArrow( Vec3(1, 0, 0), RED ) ) self.axes.append( self.CreateArrow( Vec3(0, 1, 0), GREEN ) ) self.axes.append( self.CreateArrow( Vec3(0, 0, 1), BLUE ) ) self.axes.append( self.CreateSquare( Vec3(0, 0, 0), TEAL ) ) def CreateArrow( self, vector, colour ): # Create the geometry and collision line = NodePath( Line( (0, 0, 0), vector ) ) cone = NodePath( Cone( 0.05, 0.25, axis=vector, origin=vector * 0.125 ) ) collTube = CollisionTube( (0,0,0), Point3( vector ) * 0.95, 0.05 ) # Create the axis, add the geometry and collision axis = Axis( self.name, vector, colour ) axis.AddGeometry( line, sizeStyle=SCALE ) axis.AddGeometry( cone, vector, colour ) axis.AddCollisionSolid( collTube, sizeStyle=TRANSLATE_POINT_B ) axis.reparentTo( self ) return axis def CreateSquare( self, vector, colour ): # Create the geometry and collision self.square = NodePath( Square( 0.2, 0.2, Vec3(0, 1, 0) ) ) self.square.setBillboardPointEye() collSphere = CollisionSphere( 0, 0.125 ) # Create the axis, add the geometry and collision axis = Axis( self.name, CAMERA_VECTOR, colour, planar=True, default=True ) axis.AddGeometry( self.square, sizeStyle=NONE ) axis.AddCollisionSolid( collSphere, sizeStyle=NONE ) axis.reparentTo( self ) return axis def Transform( self ): # Get the point where the mouse clicked the axis axis = self.GetSelectedAxis() axisPoint = self.GetAxisPoint( axis ) # Get the gizmo's translation matrix and transform it newTransMat = Mat4().translateMat( self.initXform.getPos() - self.getPos() + axisPoint - self.initMousePoint ) self.setMat( self.getMat() * newTransMat ) # Get the attached node path's translation matrix transVec = axisPoint - self.initMousePoint if axis.vector != CAMERA_VECTOR: transVec = self.getRelativeVector( self.rootNp, transVec ) * self.getScale()[0] newTransMat = Mat4().translateMat( transVec ) # Transform attached node paths for i, np in enumerate( self.attachedNps ): # Perform transforms in local or world space if self.local and axis.vector != CAMERA_VECTOR: transMat, rotMat, scaleMat = commonUtils.GetTrsMatrices( self.initNpXforms[i] ) np.setMat( scaleMat * newTransMat * rotMat * transMat ) else: np.setMat( self.initNpXforms[i].getMat() * newTransMat ) def OnNodeMouse1Down( self, planar, collEntry ): Base.OnNodeMouse1Down( self, planar, collEntry ) # Store the gizmo's initial transform self.initXform = self.getTransform() # If in planar mode, clear the billboard effect on the center square # and make it face the selected axis axis = self.GetSelectedAxis() if self.planar and not axis.planar: self.square.clearBillboard() self.square.lookAt( self, Point3( axis.vector ) ) else: self.square.setHpr( Vec3(0, 0, 0) ) self.square.setBillboardPointEye() def OnMouse2Down( self ): Base.OnMouse2Down( self ) # Store the gizmo's initial transform self.initXform = self.getTransform()
class Fish(NodePath): def __init__(self, fishManager, myData, index, trophy=0): NodePath.__init__(self, '%s_%d' % (myData['name'], index)) self.trophy = trophy self.myData = myData if not self.trophy: self.fishManager = fishManager self.index = index self.fsm = FishFSM(self) self.weight = random.randint(self.myData['weightRange'][0], self.myData['weightRange'][1]) else: self.weight = trophy self.adjustedScale = (self.myData['scaleRange'][1] - self.myData['scaleRange'][0]) * (self.weight - self.myData['weightRange'][0]) / (self.myData['weightRange'][1] - self.myData['weightRange'][0]) + self.myData['scaleRange'][0] self.initActor() if not self.trophy: self.initVariables() self.initFishStatusIcon() if FishingGlobals.wantDebugCollisionVisuals: self.initCollisions() self.avoidingFish = False self.biteBubbleEffect = None self.idleBubbleEffect = None self.fightBubbleEffect = None self.behaviorNameToFunction = {'straight': self.performStraightBehavior,'sineStraight': self.performSineStraightBehavior,'erratic': self.performErraticBehavior} self.sineDtAccumulator = 0.0 self.erraticDtAccumulator = 0.0 self.myZ = 0.0 if not self.trophy: self.setLightOff() return def initActor(self): self.animDict = {} for anim in FishingGlobals.fishAnimations: self.animDict[anim] = 'models/char/pir_a_gam_fsh_%s_%s.bam' % (self.myData['model'], anim) self.actor = BlendActor('models/char/pir_r_gam_fsh_%s.bam' % self.myData['model'], self.animDict, FishingGlobals.defaultFishBlendTime, FishingGlobals.fishBlendTimeDict) self.actor.reparentTo(self) self.actor.setScale(self.adjustedScale) self.mouthJoint = self.actor.exposeJoint(None, 'modelRoot', 'hookAttach') self.attractionPoint = NodePath('AttractionPoint') self.attractionPoint.reparentTo(self.mouthJoint) self.attractionPoint.setPos(0.0, 0.0, 0.0) self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdle') self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turn') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turnOpposite') if not self.trophy: self.setBin('fishingGame', 10) return def codeReload(self): self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdle') self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turn') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turnOpposite') def initFishStatusIcon(self): self.fishStatusIconTextNode = TextNode('fishBitingIcon') self.fishStatusIconNodePath = NodePath(self.fishStatusIconTextNode) self.fishStatusIconNodePath.setPos(0.0, 0.0, self.myData['indicatorHeightOffset']) self.fishStatusIconTextNode.setText('?') self.fishStatusIconTextNode.setTextColor(1.0, 0.0, 0.0, 1.0) self.fishStatusIconNodePath.reparentTo(self.mouthJoint) self.fishStatusIconNodePath.setBillboardPointEye() self.fishStatusIconNodePath.hide() self.fishStatusIconNodePath.setShaderOff() def initVariables(self): self.attractionVisual = None self.collisionVisual = None self.movingRight = True self.turnSpeed = 160.0 self.turnTowardLureInterval = None self.velocity = FishingGlobals.baseFishVelocity * self.myData['speed'] self.accel = FishingGlobals.baseFishAccel * self.myData['speed'] self.fishMoveSequence = None self.bubbleEffect = None return def initCollisions(self): self.collisionVisual = loader.loadModel('models/props/crate') self.collisionVisual.setTransparency(1) self.collisionVisual.setColor(1.0, 1.0, 1.0, 0.3) self.collisionVisual.setScale(*self.myData['collisionBoxSize']) self.collisionVisual.setPos(*self.myData['collisionBoxOffset']) self.collisionVisual.reparentTo(self) self.collisionVisual.hide() self.attractionVisual = loader.loadModel('models/ammunition/cannonball') self.attractionVisual.setTransparency(1) self.attractionVisual.setColor(0.0, 1.0, 0.0, 0.3) self.attractionVisual.setScale(self.myData['attractionRadius']) self.attractionVisual.reparentTo(self.attractionPoint) self.attractionVisual.hide() self.collisionVisualVisible = False def hide(self): NodePath.hide(self) if self.idleBubbleEffect: self.idleBubbleEffect.hide() def show(self): NodePath.show(self) if self.idleBubbleEffect: self.idleBubbleEffect.show() def reloadCollisions(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.removeNode() self.attractionVisual.removeNode() self.initCollisions() def cleanFishData(self): pass def destroy(self): self.closeFish = [] self.actor.destroy() self.stopIdleBubbleEffect() self.stopFightBubbleEffect() if self.fishMoveSequence: self.fishMoveSequence.pause() self.fishMoveSequence = None if self.fsm: del self.fsm self.fsm = None self.behaviorNameToFunction = {} self.removeNode() return def pickPositionAndSwim(self): self.initVariables() self.actor.clearControlEffectWeights() if self.myData['depth'] == 0: depth = random.uniform(FishingGlobals.fishingLevelBoundaries[self.myData['depth']], self.fishManager.gameObject.waterLevel + FishingGlobals.fishSpawnBelowWaterLevelHeight) else: depth = random.uniform(FishingGlobals.fishingLevelBoundaries[self.myData['depth']], FishingGlobals.fishingLevelBoundaries[self.myData['depth'] - 1]) startX = random.uniform(FishingGlobals.leftFishBarrier + 5.0, FishingGlobals.rightFishBarrier - 5.0) self.setPos(startX, 0.0, depth) if random.randint(0, 1): self.fsm.request('TurnAround', 'Swimming', False) else: self.fsm.request('Swimming') def turnAround(self, nextState, shouldMoveRight): if self.velocity[0] < 0 and shouldMoveRight: self.velocity[0] = -self.velocity[0] elif self.velocity[0] > 0 and not shouldMoveRight: self.velocity[0] = -self.velocity[0] self.movingRight = self.velocity[0] > 0 if self.fishMoveSequence: self.fishMoveSequence.pause() self.fishMoveSequence.clearToInitial() animationToTurn = 'turn' if self.movingRight: animationToTurn = 'turnOpposite' durationOfFishTurn = self.myData['durationOfFishTurn'] self.fishMoveSequence = Parallel(Sequence(Func(self.actor.changeAnimationTo, animationToTurn, False), Wait(durationOfFishTurn), Func(self.fsm.request, nextState)), Sequence(Wait(durationOfFishTurn * 0.33), Func(self.setXVelocity, 0.0), Wait(durationOfFishTurn * 0.66), Func(self.setXVelocity, self.velocity[0])), name='%s_turnAroundInterval' % self.getName()) self.velocity[0] = -self.velocity[0] self.fishMoveSequence.start() def setXVelocity(self, newVel): self.velocity[0] = newVel def checkForBiting(self): if self.fishManager.activeFish is not None: return if self.fishManager.gameObject.fsm.getCurrentOrNextState() not in ['Fishing', 'Reeling', 'LureStall', 'LegdFishShow']: return inv = localAvatar.getInventory() rodLvl = inv.getItemQuantity(InventoryType.FishingRod) if self.myData['depth'] + 1 > rodLvl: return self.fsm.request('Biting') return def checkForBoxOverlap(self, otherFish): pos = self.getPos(self.fishManager.gameObject.fishingSpot) size = self.myData['collisionBoxSize'] offset = list(self.myData['collisionBoxOffset']) otherPos = otherFish.getPos() otherSize = otherFish.myData['collisionBoxSize'] otherOffset = list(otherFish.myData['collisionBoxOffset']) if pos[0] + size[0] / 2.0 + offset[0] > otherPos[0] - otherSize[0] / 2.0 + otherOffset[0] and pos[0] - size[0] / 2.0 + offset[0] < otherPos[0] + otherSize[0] / 2.0 + otherOffset[0] and pos[2] + size[2] / 2.0 + offset[2] > otherPos[2] - otherSize[2] / 2.0 + otherOffset[2] and pos[2] - size[2] / 2.0 + offset[2] < otherPos[2] + otherSize[2] / 2.0 + otherOffset[2]: return True return False def checkForCloseFish(self, index): if index < len(self.fishManager.uncaughtFish) - 1: for i in range(index + 1, len(self.fishManager.uncaughtFish)): if self.fishManager.uncaughtFish[i].index != self.index: if self.checkForBoxOverlap(self.fishManager.uncaughtFish[i]): self.closeFish.append(self.fishManager.uncaughtFish[i]) if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.setColor(1, 0, 0, 0.3) if len(self.closeFish) == 0: if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.setColor(1, 1, 1, 0.3) def checkForLures(self, currentState, lurePos): if self.getX() + FishingGlobals.fishAttractionOffset < lurePos[0] and self.movingRight or self.getX() - FishingGlobals.fishAttractionOffset > lurePos[0] and not self.movingRight: if self.attractionPoint.getDistance(self.fishManager.gameObject.lure) < self.myData['attractionRadius'] + self.fishManager.gameObject.lure.lureAttractRadius: self.checkForBiting() def update(self, dt, index, lurePos): currentState = self.fsm.getCurrentOrNextState() self.closeFish = [] if currentState in ['ScareAway', 'Swimming', 'Flee', 'TurnAround']: self.checkForCloseFish(index) if currentState in ['Swimming']: self.checkForLures(currentState, lurePos) self.updateBasedOnBehavior(dt, lurePos) elif currentState in ['Hooked', 'AboutToFight', 'HookedFighting']: self.checkForCloseFish(-1) for fish in self.closeFish: self.makeFishRunFromMe(fish) def makeFishRunFromMe(self, otherFish): if otherFish.fsm.getCurrentOrNextState() == 'Flee' or otherFish.fsm.getCurrentOrNextState() == 'TurnAround': return if otherFish.getX() < self.getX(self.fishManager.gameObject.fishingSpot) and otherFish.movingRight: otherFish.fsm.request('TurnAround', 'Flee', False) elif otherFish.getX() > self.getX(self.fishManager.gameObject.fishingSpot) and not otherFish.movingRight: otherFish.fsm.request('TurnAround', 'Flee', True) else: otherFish.fsm.request('Flee') def updateBasedOnBehavior(self, dt, lurePos): currentState = self.fsm.getCurrentOrNextState() newX = self.getX() newY = self.getY() newZ = self.getZ() for fish in self.closeFish: if self.myData['size'] == 'small' and fish.myData['size'] == 'large': if self.checkForEating(fish): return self.avoidingFish = True if fish.velocity[1] > 0.0 and fish.avoidingFish: self.velocity[1] = -FishingGlobals.fishAvoidYVelocity else: self.velocity[1] = FishingGlobals.fishAvoidYVelocity if abs(fish.getY() - self.getY()) > self.myData['collisionBoxSize'][1] + fish.myData['collisionBoxSize'][1]: self.velocity[1] = 0.0 if len(self.closeFish) == 0 and abs(self.getY()) > FishingGlobals.fishYTolerance: self.avoidingFish = False if self.getY() > 0: self.velocity[1] = -FishingGlobals.fishAvoidYVelocity else: self.velocity[1] = FishingGlobals.fishAvoidYVelocity elif len(self.closeFish) == 0 and abs(self.getY()) < FishingGlobals.fishYTolerance: self.avoidingFish = False self.velocity[1] = 0.0 self.setY(0.0) newY = self.getY() + self.velocity[1] * dt + self.accel[1] * dt * dt if currentState in ['Swimming', 'TurnAround', 'Flee', 'ScareAway']: if currentState == 'ScareAway': newX, newZ = self.performScareAwayBehavior(dt, self.velocity, self.accel) else: if currentState == 'Flee': newX, newZ = self.performFleeBehavior(dt, self.velocity, self.accel) else: newX, newZ = self.behaviorNameToFunction[self.myData['behaviorDict']['name']](dt, self.velocity, self.accel) currentState = self.fsm.getCurrentOrNextState() if newX < FishingGlobals.leftFishBarrier: if currentState == 'ScareAway': if newX < FishingGlobals.leftFishBarrier - FishingGlobals.fullyOffscreenXOffset: self.fsm.request('Offscreen') return elif currentState != 'TurnAround' and not self.movingRight: self.fsm.request('TurnAround', 'Swimming', True) elif newX > FishingGlobals.rightFishBarrier: if currentState != 'TurnAround' and self.movingRight: self.fsm.request('TurnAround', 'Swimming', False) newZ = min(max(FishingGlobals.fishingLevelBoundaries[len(FishingGlobals.fishingLevelBoundaries) - 1], newZ), self.fishManager.gameObject.waterLevel + FishingGlobals.fishSpawnBelowWaterLevelHeight) self.setPos(newX, newY, newZ) def checkForEating(self, fishThatWillEat): if (self.getX() < fishThatWillEat.getX() and not fishThatWillEat.movingRight or self.getX() > fishThatWillEat.getX() and fishThatWillEat.movingRight) and self.fsm.getCurrentOrNextState() == 'Swimming' and fishThatWillEat.fsm.getCurrentOrNextState() == 'Swimming' and random.random() < 1.0: self.fsm.request('BeingEaten', fishThatWillEat) fishThatWillEat.fsm.request('Eating', self.weight) return True return False def startIdleBubbleEffect(self): self.idleBubbleEffect = FishIdleBubbleEffect.getEffect(unlimited=True) if self.idleBubbleEffect: self.idleBubbleEffect.reparentTo(self.mouthJoint) self.idleBubbleEffect.setScale(1.0) self.idleBubbleEffect.setHpr(0, 0, 0) self.idleBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.idleBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.idleBubbleEffect.particleDummy.setBin('fishingGame', 5) self.idleBubbleEffect.startLoop() def stopIdleBubbleEffect(self): if self.idleBubbleEffect: self.idleBubbleEffect.stopLoop() self.idleBubbleEffect = None return def startBiteBubbleEffect(self): self.biteBubbleEffect = FishBitingBubbleEffect.getEffect(unlimited=True) if self.biteBubbleEffect: self.biteBubbleEffect.reparentTo(self.mouthJoint) self.biteBubbleEffect.setScale(1.0) self.biteBubbleEffect.setHpr(0, 0, 0) self.biteBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.biteBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.biteBubbleEffect.particleDummy.setBin('fishingGame', 5) self.biteBubbleEffect.play() def stopBiteBubbleEffect(self): if self.biteBubbleEffect: self.biteBubbleEffect.stopLoop() self.biteBubbleEffect = None return def startFightBubbleEffect(self): self.fightBubbleEffect = FishFightingHookedBubbleEffect.getEffect(unlimited=True) if self.fightBubbleEffect: self.fightBubbleEffect.reparentTo(self.mouthJoint) self.fightBubbleEffect.setScale(1.0) self.fightBubbleEffect.setHpr(0, 0, 0) self.fightBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.fightBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.fightBubbleEffect.particleDummy.setBin('fishingGame', 5) self.fightBubbleEffect.startLoop() def stopFightBubbleEffect(self): if self.fightBubbleEffect: self.fightBubbleEffect.stopLoop() self.fightBubbleEffect = None return def performStraightBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * dt + accel[2] * dt * dt return ( newX, newZ) def performSineStraightBehavior(self, dt, velocity, accel): self.sineDtAccumulator += dt newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.myZ + math.sin(self.sineDtAccumulator) * self.myData['behaviorDict']['sineMultiplier'] return ( newX, newZ) def performScareAwayBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * FishingGlobals.scareAwayVelocityMultiplier * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * FishingGlobals.scareAwayVelocityMultiplier * dt + accel[2] * dt * dt return ( newX, newZ) def performFleeBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * FishingGlobals.fleeVelocityMultiplier * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * FishingGlobals.fleeVelocityMultiplier * dt + accel[2] * dt * dt return ( newX, newZ) def performErraticBehavior(self, dt, velocity, accel): self.erraticDtAccumulator += dt self.sineDtAccumulator += dt newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.myZ + math.sin(self.sineDtAccumulator) * self.myData['behaviorDict']['sineMultiplier'] if self.erraticDtAccumulator > self.myData['behaviorDict']['secondsBetweenChanges']: self.erraticDtAccumulator = 0 if random.random() < self.myData['behaviorDict']['chanceOfTurning']: if self.fsm.getCurrentOrNextState() != 'TurnAround': self.fsm.request('TurnAround', 'Swimming', not self.movingRight) return ( newX, newZ) def showAttractionCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.attractionVisual.show() def hideAttractionCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.attractionVisual.hide() def showAvoidanceCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.show() def hideAvoidanceCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.hide()
class FishLure(NodePath): def __init__(self, gameObject, type): NodePath.__init__(self, 'FishingLure_%s' % type) self.gameObject = gameObject self.type = type self.initLureModel() if FishingGlobals.wantDebugCollisionVisuals: self.initCollision() self.initLureHelpText() self.setLightOff() def initLureModel(self): self.lureModel = NodePath('lure') self.currentLureType = 'regular' self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[ self.currentLureType] self.lureModel = loader.loadModel( FishingGlobals.lureTypeToModel[self.currentLureType]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin('ground', 25) self.mainGui = loader.loadModel('models/gui/gui_main') def initCollision(self): self.lureCollisionVisual = loader.loadModel( 'models/ammunition/cannonball') self.lureCollisionVisual.setTransparency(1) self.lureCollisionVisual.setColor(0.0, 0.0, 1.0, 0.29999999999999999) self.lureCollisionVisual.setScale(self.lureAttractRadius) self.lureCollisionVisual.reparentTo(self) self.lureCollisionVisual.hide() def initLureHelpText(self): self.helpTextNode = TextNode('fishBitingIcon') self.helpTextNodePath = NodePath(self.helpTextNode) self.helpTextNodePath.setPos(0.0, 0.0, 0.69999999999999996) self.helpTextNode.setText(' ') self.helpTextNode.setAlign(TextNode.ACenter) self.helpTextNode.setFont(PiratesGlobals.getPirateFont()) self.helpTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.helpTextNodePath.reparentTo(self) self.helpTextNodePath.setBillboardPointEye() self.helpTextNodePath.setBin('fishingGame', 10) self.helpTextNodePath.hide() def enableLureGlow(self, glowType): self.lureGlow = LureGlow.getEffect() if self.lureGlow: if self.gameObject.fishManager.activeFish is not None: self.lureGlow.reparentTo( self.gameObject.fishManager.activeFish.mouthJoint) else: self.lureGlow.reparentTo(self) self.lureGlow.effectColor = _glowColors[glowType] self.lureGlow.setShaderOff() self.lureGlow.setBin('fishingGame', 5) self.lureGlow.play() def showHelpText(self, textToShow): taskMgr.remove( self.gameObject.distributedFishingSpot.uniqueName('ClearLureText')) if textToShow is None: self.helpTextNode.setText(' ') self.helpTextNodePath.hide() elif self.gameObject.fishManager.activeFish is not None: self.helpTextNodePath.setScale( FishingGlobals.fishSizeToHelpTextScale[ self.gameObject.fishManager.activeFish.myData['size']]) else: self.helpTextNodePath.setScale(1.0) self.helpTextNode.setText(textToShow) self.helpTextNodePath.show() taskMgr.doMethodLater( FishingGlobals.lureHelpTextDuration, self.showHelpText, name=self.gameObject.distributedFishingSpot.uniqueName( 'ClearLureText'), extraArgs=[None]) def setLureType(self, type): self.currentLureType = type if type == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) elif type == 'regular': self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[ type] self.lureModel = loader.loadModel( FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin('ground', 25) elif type == 'legendary': self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[ type] self.lureModel = loader.loadModel( FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin('ground', 25) def showCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.show() def hideCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.hide() def requestPitch(self, fish): offset = fish.getPos() - self.getPos() if fish.getX() < self.getX(): return math.degrees(math.atan2(offset.getZ(), -offset.getX())) else: return math.degrees(math.atan2(-offset.getZ(), offset.getX())) def resetLureModel(self): self.lureModel.reparentTo(self) self.lureModel.show() self.lureModel.setPosHpr(0, 0, 0, 0, 0, 0.0) if self.currentLureType == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) else: self.gameObject.gui.setTackleBoxPulse(False) def destroy(self): self.lureModel.removeNode() self.removeNode()
class Fish(NodePath): def __init__(self, fishManager, myData, index, trophy = 0): NodePath.__init__(self, '%s_%d' % (myData['name'], index)) self.trophy = trophy self.myData = myData if not self.trophy: self.fishManager = fishManager self.index = index self.fsm = FishFSM(self) self.weight = random.randint(self.myData['weightRange'][0], self.myData['weightRange'][1]) else: self.weight = trophy self.adjustedScale = (self.myData['scaleRange'][1] - self.myData['scaleRange'][0]) * (self.weight - self.myData['weightRange'][0]) / (self.myData['weightRange'][1] - self.myData['weightRange'][0]) + self.myData['scaleRange'][0] self.initActor() if not self.trophy: self.initVariables() self.initFishStatusIcon() if FishingGlobals.wantDebugCollisionVisuals: self.initCollisions() self.avoidingFish = False self.biteBubbleEffect = None self.idleBubbleEffect = None self.fightBubbleEffect = None self.behaviorNameToFunction = { 'straight': self.performStraightBehavior, 'sineStraight': self.performSineStraightBehavior, 'erratic': self.performErraticBehavior } self.sineDtAccumulator = 0.0 self.erraticDtAccumulator = 0.0 self.myZ = 0.0 if not self.trophy: self.setLightOff() def initActor(self): self.animDict = { } for anim in FishingGlobals.fishAnimations: self.animDict[anim] = 'models/char/pir_a_gam_fsh_%s_%s.bam' % (self.myData['model'], anim) self.actor = BlendActor('models/char/pir_r_gam_fsh_%s.bam' % self.myData['model'], self.animDict, FishingGlobals.defaultFishBlendTime, FishingGlobals.fishBlendTimeDict) self.actor.reparentTo(self) self.actor.setScale(self.adjustedScale) self.mouthJoint = self.actor.exposeJoint(None, 'modelRoot', 'hookAttach') self.attractionPoint = NodePath('AttractionPoint') self.attractionPoint.reparentTo(self.mouthJoint) self.attractionPoint.setPos(0.0, 0.0, 0.0) self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdle') self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turn') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turnOpposite') if not self.trophy: self.setBin('fishingGame', 10) def codeReload(self): self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdle') self.actor.setPlayRate(self.myData['speed'] * self.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turn') self.actor.setPlayRate(self.myData['speed'] * self.myData['turnAnimationMultiplier'], 'turnOpposite') def initFishStatusIcon(self): self.fishStatusIconTextNode = TextNode('fishBitingIcon') self.fishStatusIconNodePath = NodePath(self.fishStatusIconTextNode) self.fishStatusIconNodePath.setPos(0.0, 0.0, self.myData['indicatorHeightOffset']) self.fishStatusIconTextNode.setText('?') self.fishStatusIconTextNode.setTextColor(1.0, 0.0, 0.0, 1.0) self.fishStatusIconNodePath.reparentTo(self.mouthJoint) self.fishStatusIconNodePath.setBillboardPointEye() self.fishStatusIconNodePath.hide() self.fishStatusIconNodePath.setShaderOff() def initVariables(self): self.attractionVisual = None self.collisionVisual = None self.movingRight = True self.turnSpeed = 160.0 self.turnTowardLureInterval = None self.velocity = FishingGlobals.baseFishVelocity * self.myData['speed'] self.accel = FishingGlobals.baseFishAccel * self.myData['speed'] self.fishMoveSequence = None self.bubbleEffect = None def initCollisions(self): self.collisionVisual = loader.loadModel('models/props/crate') self.collisionVisual.setTransparency(1) self.collisionVisual.setColor(1.0, 1.0, 1.0, 0.29999999999999999) self.collisionVisual.setScale(*self.myData['collisionBoxSize']) self.collisionVisual.setPos(*self.myData['collisionBoxOffset']) self.collisionVisual.reparentTo(self) self.collisionVisual.hide() self.attractionVisual = loader.loadModel('models/ammunition/cannonball') self.attractionVisual.setTransparency(1) self.attractionVisual.setColor(0.0, 1.0, 0.0, 0.29999999999999999) self.attractionVisual.setScale(self.myData['attractionRadius']) self.attractionVisual.reparentTo(self.attractionPoint) self.attractionVisual.hide() self.collisionVisualVisible = False def hide(self): NodePath.hide(self) if self.idleBubbleEffect: self.idleBubbleEffect.hide() def show(self): NodePath.show(self) if self.idleBubbleEffect: self.idleBubbleEffect.show() def reloadCollisions(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.removeNode() self.attractionVisual.removeNode() self.initCollisions() def cleanFishData(self): pass def destroy(self): self.closeFish = [] self.actor.destroy() self.stopIdleBubbleEffect() self.stopFightBubbleEffect() if self.fishMoveSequence: self.fishMoveSequence.pause() self.fishMoveSequence = None if self.fsm: del self.fsm self.fsm = None self.behaviorNameToFunction = { } self.removeNode() def pickPositionAndSwim(self): self.initVariables() self.actor.clearControlEffectWeights() if self.myData['depth'] == 0: depth = random.uniform(FishingGlobals.fishingLevelBoundaries[self.myData['depth']], self.fishManager.gameObject.waterLevel + FishingGlobals.fishSpawnBelowWaterLevelHeight) else: depth = random.uniform(FishingGlobals.fishingLevelBoundaries[self.myData['depth']], FishingGlobals.fishingLevelBoundaries[self.myData['depth'] - 1]) startX = random.uniform(FishingGlobals.leftFishBarrier + 5.0, FishingGlobals.rightFishBarrier - 5.0) self.setPos(startX, 0.0, depth) if random.randint(0, 1): self.fsm.request('TurnAround', 'Swimming', False) else: self.fsm.request('Swimming') def turnAround(self, nextState, shouldMoveRight): if self.velocity[0] < 0 and shouldMoveRight: self.velocity[0] = -self.velocity[0] elif self.velocity[0] > 0 and not shouldMoveRight: self.velocity[0] = -self.velocity[0] self.movingRight = self.velocity[0] > 0 if self.fishMoveSequence: self.fishMoveSequence.pause() self.fishMoveSequence.clearToInitial() animationToTurn = 'turn' if self.movingRight: animationToTurn = 'turnOpposite' durationOfFishTurn = self.myData['durationOfFishTurn'] self.fishMoveSequence = Parallel(Sequence(Func(self.actor.changeAnimationTo, animationToTurn, False), Wait(durationOfFishTurn), Func(self.fsm.request, nextState)), Sequence(Wait(durationOfFishTurn * 0.33000000000000002), Func(self.setXVelocity, 0.0), Wait(durationOfFishTurn * 0.66000000000000003), Func(self.setXVelocity, self.velocity[0])), name = '%s_turnAroundInterval' % self.getName()) self.velocity[0] = -self.velocity[0] self.fishMoveSequence.start() def setXVelocity(self, newVel): self.velocity[0] = newVel def checkForBiting(self): if self.fishManager.activeFish is not None: return None if self.fishManager.gameObject.fsm.getCurrentOrNextState() not in [ 'Fishing', 'Reeling', 'LureStall', 'LegdFishShow']: return None inv = localAvatar.getInventory() rodLvl = inv.getItemQuantity(InventoryType.FishingRod) if self.myData['depth'] + 1 > rodLvl: return None self.fsm.request('Biting') def checkForBoxOverlap(self, otherFish): pos = self.getPos(self.fishManager.gameObject.fishingSpot) size = self.myData['collisionBoxSize'] offset = list(self.myData['collisionBoxOffset']) otherPos = otherFish.getPos() otherSize = otherFish.myData['collisionBoxSize'] otherOffset = list(otherFish.myData['collisionBoxOffset']) if pos[0] + size[0] / 2.0 + offset[0] > (otherPos[0] - otherSize[0] / 2.0) + otherOffset[0] and (pos[0] - size[0] / 2.0) + offset[0] < otherPos[0] + otherSize[0] / 2.0 + otherOffset[0] and pos[2] + size[2] / 2.0 + offset[2] > (otherPos[2] - otherSize[2] / 2.0) + otherOffset[2] and (pos[2] - size[2] / 2.0) + offset[2] < otherPos[2] + otherSize[2] / 2.0 + otherOffset[2]: return True return False def checkForCloseFish(self, index): if index < len(self.fishManager.uncaughtFish) - 1: for i in range(index + 1, len(self.fishManager.uncaughtFish)): if self.fishManager.uncaughtFish[i].index != self.index: if self.checkForBoxOverlap(self.fishManager.uncaughtFish[i]): self.closeFish.append(self.fishManager.uncaughtFish[i]) if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.setColor(1, 0, 0, 0.29999999999999999) self.checkForBoxOverlap(self.fishManager.uncaughtFish[i]) if len(self.closeFish) == 0: if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.setColor(1, 1, 1, 0.29999999999999999) def checkForLures(self, currentState, lurePos): if (self.getX() + FishingGlobals.fishAttractionOffset < lurePos[0] or self.movingRight or self.getX() - FishingGlobals.fishAttractionOffset > lurePos[0]) and not (self.movingRight): if self.attractionPoint.getDistance(self.fishManager.gameObject.lure) < self.myData['attractionRadius'] + self.fishManager.gameObject.lure.lureAttractRadius: self.checkForBiting() def update(self, dt, index, lurePos): currentState = self.fsm.getCurrentOrNextState() self.closeFish = [] if currentState in [ 'ScareAway', 'Swimming', 'Flee', 'TurnAround']: self.checkForCloseFish(index) if currentState in [ 'Swimming']: self.checkForLures(currentState, lurePos) self.updateBasedOnBehavior(dt, lurePos) elif currentState in [ 'Hooked', 'AboutToFight', 'HookedFighting']: self.checkForCloseFish(-1) for fish in self.closeFish: self.makeFishRunFromMe(fish) def makeFishRunFromMe(self, otherFish): if otherFish.fsm.getCurrentOrNextState() == 'Flee' or otherFish.fsm.getCurrentOrNextState() == 'TurnAround': return None if otherFish.getX() < self.getX(self.fishManager.gameObject.fishingSpot) and otherFish.movingRight: otherFish.fsm.request('TurnAround', 'Flee', False) elif otherFish.getX() > self.getX(self.fishManager.gameObject.fishingSpot) and not (otherFish.movingRight): otherFish.fsm.request('TurnAround', 'Flee', True) else: otherFish.fsm.request('Flee') def updateBasedOnBehavior(self, dt, lurePos): currentState = self.fsm.getCurrentOrNextState() newX = self.getX() newY = self.getY() newZ = self.getZ() for fish in self.closeFish: if self.myData['size'] == 'small' and fish.myData['size'] == 'large': if self.checkForEating(fish): return None self.avoidingFish = True if fish.velocity[1] > 0.0 and fish.avoidingFish: self.velocity[1] = -(FishingGlobals.fishAvoidYVelocity) else: self.velocity[1] = FishingGlobals.fishAvoidYVelocity if abs(fish.getY() - self.getY()) > self.myData['collisionBoxSize'][1] + fish.myData['collisionBoxSize'][1]: self.velocity[1] = 0.0 continue if len(self.closeFish) == 0 and abs(self.getY()) > FishingGlobals.fishYTolerance: self.avoidingFish = False if self.getY() > 0: self.velocity[1] = -(FishingGlobals.fishAvoidYVelocity) else: self.velocity[1] = FishingGlobals.fishAvoidYVelocity elif len(self.closeFish) == 0 and abs(self.getY()) < FishingGlobals.fishYTolerance: self.avoidingFish = False self.velocity[1] = 0.0 self.setY(0.0) newY = self.getY() + self.velocity[1] * dt + self.accel[1] * dt * dt if currentState in [ 'Swimming', 'TurnAround', 'Flee', 'ScareAway']: if currentState == 'ScareAway': (newX, newZ) = self.performScareAwayBehavior(dt, self.velocity, self.accel) elif currentState == 'Flee': (newX, newZ) = self.performFleeBehavior(dt, self.velocity, self.accel) else: (newX, newZ) = self.behaviorNameToFunction[self.myData['behaviorDict']['name']](dt, self.velocity, self.accel) currentState = self.fsm.getCurrentOrNextState() if newX < FishingGlobals.leftFishBarrier: if currentState == 'ScareAway': if newX < FishingGlobals.leftFishBarrier - FishingGlobals.fullyOffscreenXOffset: self.fsm.request('Offscreen') return None elif currentState != 'TurnAround' and not (self.movingRight): self.fsm.request('TurnAround', 'Swimming', True) elif newX > FishingGlobals.rightFishBarrier: if currentState != 'TurnAround' and self.movingRight: self.fsm.request('TurnAround', 'Swimming', False) newZ = min(max(FishingGlobals.fishingLevelBoundaries[len(FishingGlobals.fishingLevelBoundaries) - 1], newZ), self.fishManager.gameObject.waterLevel + FishingGlobals.fishSpawnBelowWaterLevelHeight) self.setPos(newX, newY, newZ) def checkForEating(self, fishThatWillEat): if (self.getX() < fishThatWillEat.getX() or not (fishThatWillEat.movingRight) or self.getX() > fishThatWillEat.getX() or fishThatWillEat.movingRight) and self.fsm.getCurrentOrNextState() == 'Swimming' and fishThatWillEat.fsm.getCurrentOrNextState() == 'Swimming' and random.random() < 1.0: self.fsm.request('BeingEaten', fishThatWillEat) fishThatWillEat.fsm.request('Eating', self.weight) return True return False def startIdleBubbleEffect(self): self.idleBubbleEffect = FishIdleBubbleEffect.getEffect(unlimited = True) if self.idleBubbleEffect: self.idleBubbleEffect.reparentTo(self.mouthJoint) self.idleBubbleEffect.setScale(1.0) self.idleBubbleEffect.setHpr(0, 0, 0) self.idleBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.idleBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.idleBubbleEffect.particleDummy.setBin('fishingGame', 5) self.idleBubbleEffect.startLoop() def stopIdleBubbleEffect(self): if self.idleBubbleEffect: self.idleBubbleEffect.stopLoop() self.idleBubbleEffect = None def startBiteBubbleEffect(self): self.biteBubbleEffect = FishBitingBubbleEffect.getEffect(unlimited = True) if self.biteBubbleEffect: self.biteBubbleEffect.reparentTo(self.mouthJoint) self.biteBubbleEffect.setScale(1.0) self.biteBubbleEffect.setHpr(0, 0, 0) self.biteBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.biteBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.biteBubbleEffect.particleDummy.setBin('fishingGame', 5) self.biteBubbleEffect.play() def stopBiteBubbleEffect(self): if self.biteBubbleEffect: self.biteBubbleEffect.stopLoop() self.biteBubbleEffect = None def startFightBubbleEffect(self): self.fightBubbleEffect = FishFightingHookedBubbleEffect.getEffect(unlimited = True) if self.fightBubbleEffect: self.fightBubbleEffect.reparentTo(self.mouthJoint) self.fightBubbleEffect.setScale(1.0) self.fightBubbleEffect.setHpr(0, 0, 0) self.fightBubbleEffect.setLifespanBasedOnDepth(self.getPos(render)) self.fightBubbleEffect.setBubbleSizeBasedOnWeight(self.weight) self.fightBubbleEffect.particleDummy.setBin('fishingGame', 5) self.fightBubbleEffect.startLoop() def stopFightBubbleEffect(self): if self.fightBubbleEffect: self.fightBubbleEffect.stopLoop() self.fightBubbleEffect = None def performStraightBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * dt + accel[2] * dt * dt return (newX, newZ) def performSineStraightBehavior(self, dt, velocity, accel): self.sineDtAccumulator += dt newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.myZ + math.sin(self.sineDtAccumulator) * self.myData['behaviorDict']['sineMultiplier'] return (newX, newZ) def performScareAwayBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * FishingGlobals.scareAwayVelocityMultiplier * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * FishingGlobals.scareAwayVelocityMultiplier * dt + accel[2] * dt * dt return (newX, newZ) def performFleeBehavior(self, dt, velocity, accel): newX = self.getX() + velocity[0] * FishingGlobals.fleeVelocityMultiplier * dt + accel[0] * dt * dt newZ = self.getZ() + velocity[2] * FishingGlobals.fleeVelocityMultiplier * dt + accel[2] * dt * dt return (newX, newZ) def performErraticBehavior(self, dt, velocity, accel): self.erraticDtAccumulator += dt self.sineDtAccumulator += dt newX = self.getX() + velocity[0] * dt + accel[0] * dt * dt newZ = self.myZ + math.sin(self.sineDtAccumulator) * self.myData['behaviorDict']['sineMultiplier'] if self.erraticDtAccumulator > self.myData['behaviorDict']['secondsBetweenChanges']: self.erraticDtAccumulator = 0 if random.random() < self.myData['behaviorDict']['chanceOfTurning']: if self.fsm.getCurrentOrNextState() != 'TurnAround': self.fsm.request('TurnAround', 'Swimming', not (self.movingRight)) return (newX, newZ) def showAttractionCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.attractionVisual.show() def hideAttractionCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.attractionVisual.hide() def showAvoidanceCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.show() def hideAvoidanceCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.collisionVisual.hide()