Esempio n. 1
0
class Player():
    def __init__(self):
        self.name = 'Player'
        self.points = 0
        self.isPlayer = True
        self.isAttacking = False
        self.isAlive = True

        self.attackTimer = Timer(0.0)

    def advance(self, deltaTime: float):
        self.attackTimer.advance(deltaTime)

        if self.attackTimer.timeIsUp():
            self.isAttacking = False
            self.attackTimer.setActive(False)

    def setAttacking(self, attackTime: float):
        self.isAttacking = True

        self.attackTimer.setTimer(attackTime)
        self.attackTimer.start()

    def setAlive(self, alive):
        self.isAlive = alive

    def __repr__(self):
        return "Player"
Esempio n. 2
0
class StateChase(State):
    name = "chase"

    def __init__(self, brain):
        State.__init__(self, brain)
        meEnemy = self.brain.owner.world.component_for_entity(
            self.brain.owner.entity, system.gamelogic.enemy.Enemy)

        # basically move speed
        self.lastInputTimer = Timer(meEnemy.enemyInfo.chaseStepDelay,
                                    instant=True)

        # try attacking when timer is finished
        self.canAttackTimer = Timer()

        # we need to know player location, or we could just handle on every new
        # PlayerLocation message
        self.lastKnownPlayerPosition = None

    def on_enter(self):
        meEnemy = self.brain.owner.world.component_for_entity(
            self.brain.owner.entity, system.gamelogic.enemy.Enemy)

        stateTimeRnd = random.randrange(-100 * meEnemy.enemyInfo.chaseTimeRnd,
                                        100 * meEnemy.enemyInfo.chaseTimeRnd)
        self.setTimer(meEnemy.enemyInfo.chaseTime + (stateTimeRnd / 100))

        self.canAttackTimer.setTimer(meEnemy.enemyInfo.enemyCanAttackPeriod)
        self.canAttackTimer.reset()

        if not Config.allowEnemyAttacking:
            self.canAttackTimer.setActive(False)

    def tryAttacking(self):
        if self.canAttackTimer.timeIsUp():
            logger.debug("{}: Check if i can attack player".format(self.name))
            if self.canAttackPlayer():
                if (EntityFinder.numEnemiesInState(self.brain.owner.world,
                                                   'attack') <
                        Config.maxEnemiesInStateAttacking):
                    self.brain.pop()
                    self.brain.push("attackwindup")

            self.canAttackTimer.reset()

    def tryMoving(self):
        # only move if we can not hit him (even on cooldown)
        # this is quiet... taxing. and not really necessary?
        # if not self.canAttackPlayer():

        if True:
            # movement speed, and direction
            if self.lastInputTimer.timeIsUp():
                self.getInputChase()
                self.lastInputTimer.reset()

    def trySkill(self):
        # stickfigure has no skills
        pass

    def process(self, dt):
        meAttackable = self.brain.owner.world.component_for_entity(
            self.brain.owner.entity, system.gamelogic.attackable.Attackable)

        if meAttackable.isStunned:
            return

        self.lastInputTimer.advance(dt)
        self.canAttackTimer.advance(dt)

        # update player position if new location
        self.checkForNewPlayerPosition()

        self.tryAttacking()
        # note that if we want to attack, as identified a few lines above,
        # we will be in state attackWindup, and not reach here
        self.trySkill()
        self.tryMoving()

        # switch to wander if exhausted
        if self.timeIsUp():
            logger.debug("{}: Too long chasing, switching to wander".format(
                self.owner))
            self.brain.pop()
            self.brain.push("wander")

    def checkForNewPlayerPosition(self):
        # check if there are any new player position messages
        for message in messaging.getByType(MessageType.PlayerLocation):
            self.lastKnownPlayerPosition = message.data

    def canAttackPlayer(self):
        if self.lastKnownPlayerPosition is None:
            # we may not yet have received a location.
            # find it directly via player entity
            # this is every time we go into chase state
            playerEntity = EntityFinder.findPlayer(self.brain.owner.world)
            # player not spawned
            if playerEntity is not None:
                playerRenderable = self.brain.owner.world.component_for_entity(
                    playerEntity, system.graphics.renderable.Renderable)
                self.lastKnownPlayerPosition = playerRenderable.getLocationAndSize(
                )

        canAttack = AiHelper.canAttackPlayer(self.brain.owner,
                                             self.lastKnownPlayerPosition)

        return canAttack

    def getInputChase(self):
        meGroupId = self.brain.owner.world.component_for_entity(
            self.brain.owner.entity, system.groupid.GroupId)
        meRenderable = self.brain.owner.world.component_for_entity(
            self.brain.owner.entity, system.graphics.renderable.Renderable)

        if not Config.allowEnemyMovement:
            return

        moveX, moveY, dontChangeDirection = AiHelper.getAttackVectorToPlayer(
            self.owner, meRenderable)

        # only move if we really move a character
        if moveX != 0 or moveY != 0:
            directMessaging.add(
                groupId=meGroupId.getId(),
                type=DirectMessageType.moveEnemy,
                data={
                    'x': moveX,
                    'y': moveY,
                    'dontChangeDirection': dontChangeDirection,
                    'updateTexture': True,
                    'force': False,
                },
            )
Esempio n. 3
0
class Attackable():
    def __init__(self,
                 initialHealth=100,
                 stunTime=0.75,
                 stunCount=3,
                 stunTimeFrame=3,
                 knockdownChance=0.0,
                 knockbackChance=0.0):
        self.health = initialHealth
        self.initialHealth = initialHealth

        self.knockdownChance = knockdownChance
        self.knockbackChance = knockbackChance

        self.maxStunCount = stunCount
        self.stunTimeFrame = stunTimeFrame
        self.stunTime = stunTime
        self.isStunned = False
        self.stunTimer = Timer(0.0)
        self.stunTimer.setActive(False)
        self.stunnedQueue = collections.deque(maxlen=5)

        # after message GameRestart, all Renderables are deleted - but not until
        # the next advance(). Upon restarting the map, if the user presses a key,
        # checkHeal() in AttackableProcessor would emit yet another stray
        # GameOver message. This is the fix.
        self.isActive = True

    def setActive(self, active):
        self.isActive = active

    def isStunnable(self):
        if self.maxStunCount == 0:
            return False

        timeRef = system.singletons.gametime.getGameTime() - self.stunTimeFrame
        stunCount = 0
        for stunned in self.stunnedQueue:
            if stunned['time'] > timeRef:
                stunCount += 1

        if stunCount <= self.maxStunCount:
            logging.info(
                "Stun check: Can be stunned Cnt: {} max: {} time: {}".format(
                    stunCount, self.maxStunCount, timeRef))
            return True
        else:
            logging.info(
                "Stun check: Can not be stunned Cnt: {} max: {} time: {}".
                format(stunCount, self.maxStunCount, timeRef))
            return False

    def addStun(self, stunTime):
        self.stunnedQueue.append({
            'time':
            system.singletons.gametime.getGameTime(),
            'stunTime':
            stunTime
        })

    def resetHealth(self):
        self.health = self.initialHealth

    def adjustHealth(self, health: int):
        self.health += health

    def getHealth(self):
        return self.health

    def getHealthPercentage(self):
        p = self.health / self.initialHealth
        return p

    def advance(self, dt):
        self.stunTimer.advance(dt)

    def setHealth(self, health):
        self.health = health
        self.initialHealth = health

    def setStunTime(self, stunTime):
        self.stunTime = stunTime

    def setStunTimeFrame(self, stunTimeFrame):
        self.stunTimeFrame = stunTimeFrame

    def setMaxStunCount(self, maxStunCount):
        self.maxStunCount = maxStunCount

    def setKnockdownChance(self, knockdownChance):
        self.knockdownChance = knockdownChance

    def setKnockbackChance(self, knockbackChance):
        self.knockbackChance = knockbackChance