Example #1
0
    def spawn(self, position, place=True, spawnTime=None, spawnDelay=0.1, radius=5, radiusTo=None, monster=None, check=False):
        if spawnDelay:
            return reactor.callLater(spawnDelay, self.spawn, position, place, spawnTime, 0, radius, radiusTo, monster, check)
        else:
            if place:
                tile = position.getTile()
                if not tile:
                    log.msg("Spawning of creature('%s') on %s failed. Tile does not exist!" % (self.data["name"], str(position)))
                    return

            if not monster:
                monster = Monster(self, position, None)
                if not self.prepared:
                    self.prepare()

            if not monster.alive:
                monster.data = monster.base.data.copy()
                monster.alive = True
            
            if not monster.clientId() in allCreatures:
                allCreatures[monster.clientId()] = monster
                
            monster.lastDamagers.clear()
            
            if place:
                # Vertify that there are no spectators if check = True
                if check and hasSpectators(position): 
                    # If so, try again in 10s
                    reactor.callLater(10, self.spawn, position, place, spawnTime, 0, radius, radiusTo, monster, check)
                    return
                    
                elif tile.hasCreatures() and config.tryToSpawnCreaturesNextToEachother:
                    ok = False
                    for testx in (-1,0,1):
                        position[0] += testx
                        tile = position.getTile()
                        if not tile:
                            continue
                        elif tile.hasCreatures():
                            for testy in (-1,0,1):
                                position[0] += testy
                                tile = position.getTile()
                                if not tile:
                                    continue
                                
                                if not tile.hasCreatures():
                                    try:
                                        stackpos = map.getTile(position).placeCreature(monster)
                                        ok = True
                                    except:
                                        pass
                                    break
                        else:
                            
                            try:
                                stackpos = map.getTile(position).placeCreature(monster)
                                ok = True
                            except:
                                pass
                        if ok:
                            break
                    if not ok:
                        log.msg("Spawning of creature('%s') on %s failed" % (self.data["name"], str(position)))
                        return
                elif not tile.hasCreatures() or config.tryToSpawnCreatureRegardlessOfCreatures:
                    try:
                        stackpos = tile.placeCreature(monster)
                    except:
                        log.msg("Spawning of creature('%s') on %s failed" % (self.data["name"], str(position)))
                        return
                else:
                    log.msg("Spawning of creature('%s') on %s failed" % (self.data["name"], str(position)))
                    return
                
            monster.spawnTime = spawnTime
            monster.radius = radius
            
            if radius <= 1:
                self.walkable = False
            if radiusTo:
                monster.radiusTo = radiusTo
            else:
                monster.radiusTo = (position[0], position[1])

            if place and stackpos and stackpos < 10:
                for player in getPlayers(position):
                    stream = player.packet()
                    stream.addTileCreature(position, stackpos, monster, player)
                            
                    stream.send(player.client) 
                        
            self.brain.beginThink(monster) # begin the heavy thought process!
            
            return monster
Example #2
0
    def spawn(self,
              position,
              place=True,
              spawnTime=None,
              spawnDelay=0.1,
              radius=5,
              radiusTo=None,
              monster=None,
              check=False):
        if spawnDelay:
            return reactor.callLater(spawnDelay, self.spawn, position, place,
                                     spawnTime, 0, radius, radiusTo, monster,
                                     check)
        else:
            if place:
                tile = position.getTile()
                if not tile:
                    log.msg(
                        "Spawning of creature('%s') on %s failed. Tile does not exist!"
                        % (self.data["name"], str(position)))
                    return

            if not monster:
                monster = Monster(self, position, None)
                if not self.prepared:
                    self.prepare()

            if not monster.alive:
                monster.data = monster.base.data.copy()
                monster.alive = True

            if not monster.clientId() in allCreatures:
                allCreatures[monster.clientId()] = monster

            monster.lastDamagers.clear()

            if place:
                # Vertify that there are no spectators if check = True
                if check and hasSpectators(position):
                    # If so, try again in 10s
                    reactor.callLater(10, self.spawn, position, place,
                                      spawnTime, 0, radius, radiusTo, monster,
                                      check)
                    return

                elif tile.hasCreatures(
                ) and config.tryToSpawnCreaturesNextToEachother:
                    ok = False
                    for testx in (-1, 0, 1):
                        position[0] += testx
                        tile = position.getTile()
                        if not tile:
                            continue
                        elif tile.hasCreatures():
                            for testy in (-1, 0, 1):
                                position[0] += testy
                                tile = position.getTile()
                                if not tile:
                                    continue

                                if not tile.hasCreatures():
                                    try:
                                        stackpos = map.getTile(
                                            position).placeCreature(monster)
                                        ok = True
                                    except:
                                        pass
                                    break
                        else:

                            try:
                                stackpos = map.getTile(position).placeCreature(
                                    monster)
                                ok = True
                            except:
                                pass
                        if ok:
                            break
                    if not ok:
                        log.msg("Spawning of creature('%s') on %s failed" %
                                (self.data["name"], str(position)))
                        return
                elif not tile.hasCreatures(
                ) or config.tryToSpawnCreatureRegardlessOfCreatures:
                    try:
                        stackpos = tile.placeCreature(monster)
                    except:
                        log.msg("Spawning of creature('%s') on %s failed" %
                                (self.data["name"], str(position)))
                        return
                else:
                    log.msg("Spawning of creature('%s') on %s failed" %
                            (self.data["name"], str(position)))
                    return

            monster.spawnTime = spawnTime
            monster.radius = radius

            if radius <= 1:
                self.walkable = False
            if radiusTo:
                monster.radiusTo = radiusTo
            else:
                monster.radiusTo = (position[0], position[1])

            if place and stackpos and stackpos < 10:
                for player in getPlayers(position):
                    stream = player.packet()
                    stream.addTileCreature(position, stackpos, monster, player)

                    stream.send(player.client)

            self.brain.beginThink(monster)  # begin the heavy thought process!

            return monster
Example #3
0
    def onDeath(self):
        # Remove master summons
        isSummon = self.isSummon()

        if self.master:
            self.master.activeSummons.remove(self)

        self.turnOffBrain()
        
        # Remove summons
        if self.activeSummons:
            for summon in self.activeSummons:
                summon.magicEffect(EFFECT_POFF)
                summon.despawn()
                summon.turnOffBrain()

        # Lose all conditions.
        self.loseAllConditions()
                
        # Transform
        tile = map.getTile(self.position)
        lootMsg = []
        if self.base.data["corpse"]:
            corpse = game.item.Item(self.base.data["corpse"], actions=self.base.corpseAction)
            
            corpse.movable = False
            def _move_corpse():
                corpse.movable = True

            callLater(config.moveCorpseAfter, _move_corpse)

            # Set owner.
            if self.lastDamagers:
                if self.getLastDamager().isPlayer():
                    corpse.owners = [self.getLastDamager()]
            
                    def _clear_private_loot():
                        del corpse.owners
                
                    # Callback to remove owner after config.privateLootFor seconds
                    callLater(config.privateLootFor, _clear_private_loot)
            if not isSummon and not self.lastDamagers or self.getLastDamager() != self.master:
                try:
                    maxSize = game.item.items[self.base.data["corpse"]]["containerSize"]
                except:
                    # Monsters with loot MUST have a container with some size in it.
                    if self.base.lootTable: 
                        print "[WARNING] Monster %s got a bad corpse" % self.name()
                    maxSize = 0
                drops = []
                if maxSize:
                    for loot in self.base.lootTable:
                        if config.lootDropRate*loot[1]*100 > random.randint(0, 10000): # [7363, 28.5, 4]
                            if len(drops)+1 == maxSize:
                                if config.stockLootInBagsIfNeeded:
                                    drops.insert(0, (config.stockLootBagId, None))
                                    maxSize += item.items[config.stockLootBagId]["containerSize"]
                                else:
                                    drops.append(loot)            
                                break
                            else:        
                                drops.append(loot)
                            
                        elif len(loot) == 4:
                            drops.append((loot[0], None, loot[4]))
                
                ret = scriptsystem.get("loot").runSync(self, self.getLastDamager() if self.lastDamagers else None, loot=drops, maxSize=maxSize)
                if type(ret) == list:
                    drops = ret

                for loot in drops:
                    lenLoot = len(loot)
                    ret = 0
                    if lenLoot == 2:
                        ritem = game.item.Item(random.choice(loot[0]) if isinstance(loot[0], list) else loot[0], 1)
                        lootMsg.append(ritem.name)
                        ret = corpse.placeItemRecursive(ritem)
                            
                    elif lenLoot == 3:
                        count = random.randint(1, loot[2]) * config.lootMaxRate
                        if count > 100:
                            while count:
                                depCount = min(count, 100)
                                ritem = game.item.Item(random.choice(loot[0]) if isinstance(loot[0], list) else loot[0], depCount)
                                lootMsg.append(ritem.name)
                                ret = corpse.placeItemRecursive(ritem)
                                count -= depCount
                        else:
                            ritem = game.item.Item(random.choice(loot[0]) if isinstance(loot[0], list) else loot[0], count)
                            lootMsg.append(ritem.name)
                            ret = corpse.placeItemRecursive(ritem)
                                
                    elif lenLoot == 4:
                        count = random.randint(loot[4], loot[2]) * config.lootMaxRate
                        if count > 100:
                            while count:
                                depCount = min(count, 100)
                                ritem = game.item.Item(random.choice(loot[0]) if isinstance(loot[0], list) else loot[0], depCount)
                                lootMsg.append(ritem.name)
                                ret = corpse.placeItemRecursive(ritem)
                                count -= depCount
                                    
                        else:
                            ritem = game.item.Item(random.choice(loot[0]) if isinstance(loot[0], list) else loot[0], count)
                            lootMsg.append(ritem.name)
                            ret = corpse.placeItemRecursive(ritem)
                                

                    if ret == None:
                        log.msg("Warning: Monster '%s' extends all possible loot space" % self.data['name'])
                        break

        else:
            corpse = None
            
        scriptsystem.get("death").runSync(self, self.getLastDamager() if self.lastDamagers else None, corpse=corpse)
        if self.alive or self.data["health"] > 0:
            print "[May bug] Death events brought us back to life?"
            return
        
        # Remove bpth small and full splashes on the tile.
        for item in tile.getItems():
            if item.itemId in SMALLSPLASHES or item.itemId in FULLSPLASHES:
                tile.removeItem(item)
        
        # Add full splash
        splash = Item(FULLSPLASH)
        splash.fluidSource = self.base.blood
        
        if corpse:
            corpse.place(self.position)
        splash.place(self.position)
        
        # Start decay
        if corpse:
            corpse.decay()
        splash.decay()
        
        # Remove me. This also refresh the tile.
        self.remove()

        if not isSummon and self.lastDamagers and self.getLastDamager().isPlayer() and self.getLastDamager() != self.master:
            if lootMsg:
                self.getLastDamager().message(_l(self.getLastDamager(), "loot of %(who)s: %(loot)s") % {"who": self.data["name"].lower(), "loot": ', '.join(lootMsg)}, MSG_LOOT)
            else:
                self.getLastDamager().message(_l(self.getLastDamager(), "loot of %s: nothing") % (self.data["name"]), MSG_LOOT)
                
            # Experience split.
            attackerParty = self.getLastDamager().party()
            if attackerParty and attackerParty.shareExperience and attackerParty.checkShareExperience():
                for member in attackerParty.members:
                    if member.data["stamina"] or config.noStaminaNoExp == False:
                        exp = (self.base.experience / len(attackerParty.members)) * config.partyExperienceFactor
                        member.modifyExperience(exp * member.getExperienceRate())
                        
                        if exp >= member.data["level"]:
                            member.soulGain()
            else:
                if self.getLastDamager().data["stamina"] or config.noStaminaNoExp == False:
                    self.getLastDamager().modifyExperience(self.base.experience *self.getLastDamager().getExperienceRate())

                    if self.base.experience >= self.getLastDamager().data["level"]:
                        self.getLastDamager().soulGain()
       
        # Begin respawn
        if self.respawn:
            self.position = self.spawnPosition
            self.target = None
            self.targetMode = 0
            if self.spawnTime != 0:
                if self.spawnTime:
                    reactor.callLater(self.spawnTime, self.base.spawn, self.spawnPosition, spawnTime = self.spawnTime, spawnDelay=0, check=False)
                else:
                    return
            else:
                reactor.callLater(self.base.spawnTime, self.base.spawn, self.spawnPosition, spawnDelay=0, check=False)
Example #4
0
    def onDeath(self):
        # Remove master summons
        isSummon = self.isSummon()

        if self.master:
            self.master.activeSummons.remove(self)

        self.turnOffBrain()

        # Remove summons
        if self.activeSummons:
            for summon in self.activeSummons:
                summon.magicEffect(EFFECT_POFF)
                summon.despawn()
                summon.turnOffBrain()

        # Lose all conditions.
        self.loseAllConditions()

        # Transform
        tile = map.getTile(self.position)
        lootMsg = []
        if self.base.data["corpse"]:
            corpse = game.item.Item(self.base.data["corpse"],
                                    actions=self.base.corpseAction)

            corpse.movable = False

            def _move_corpse():
                corpse.movable = True

            callLater(config.moveCorpseAfter, _move_corpse)

            # Set owner.
            if self.lastDamagers:
                if self.getLastDamager().isPlayer():
                    corpse.owners = [self.getLastDamager()]

                    def _clear_private_loot():
                        del corpse.owners

                    # Callback to remove owner after config.privateLootFor seconds
                    callLater(config.privateLootFor, _clear_private_loot)
            if not isSummon and not self.lastDamagers or self.getLastDamager(
            ) != self.master:
                try:
                    maxSize = game.item.items[
                        self.base.data["corpse"]]["containerSize"]
                except:
                    # Monsters with loot MUST have a container with some size in it.
                    if self.base.lootTable:
                        print "[WARNING] Monster %s got a bad corpse" % self.name(
                        )
                    maxSize = 0
                drops = []
                if maxSize:
                    for loot in self.base.lootTable:
                        if config.lootDropRate * loot[1] * 100 > random.randint(
                                0, 10000):  # [7363, 28.5, 4]
                            if len(drops) + 1 == maxSize:
                                if config.stockLootInBagsIfNeeded:
                                    drops.insert(0,
                                                 (config.stockLootBagId, None))
                                    maxSize += item.items[
                                        config.stockLootBagId]["containerSize"]
                                else:
                                    drops.append(loot)
                                break
                            else:
                                drops.append(loot)

                        elif len(loot) == 4:
                            drops.append((loot[0], None, loot[4]))

                ret = scriptsystem.get("loot").runSync(
                    self,
                    self.getLastDamager() if self.lastDamagers else None,
                    loot=drops,
                    maxSize=maxSize)
                if type(ret) == list:
                    drops = ret

                for loot in drops:
                    lenLoot = len(loot)
                    ret = 0
                    if lenLoot == 2:
                        ritem = game.item.Item(
                            random.choice(loot[0]) if isinstance(
                                loot[0], list) else loot[0], 1)
                        lootMsg.append(ritem.name)
                        ret = corpse.placeItemRecursive(ritem)

                    elif lenLoot == 3:
                        count = random.randint(1, loot[2]) * config.lootMaxRate
                        if count > 100:
                            while count:
                                depCount = min(count, 100)
                                ritem = game.item.Item(
                                    random.choice(loot[0]) if isinstance(
                                        loot[0], list) else loot[0], depCount)
                                lootMsg.append(ritem.name)
                                ret = corpse.placeItemRecursive(ritem)
                                count -= depCount
                        else:
                            ritem = game.item.Item(
                                random.choice(loot[0]) if isinstance(
                                    loot[0], list) else loot[0], count)
                            lootMsg.append(ritem.name)
                            ret = corpse.placeItemRecursive(ritem)

                    elif lenLoot == 4:
                        count = random.randint(loot[4],
                                               loot[2]) * config.lootMaxRate
                        if count > 100:
                            while count:
                                depCount = min(count, 100)
                                ritem = game.item.Item(
                                    random.choice(loot[0]) if isinstance(
                                        loot[0], list) else loot[0], depCount)
                                lootMsg.append(ritem.name)
                                ret = corpse.placeItemRecursive(ritem)
                                count -= depCount

                        else:
                            ritem = game.item.Item(
                                random.choice(loot[0]) if isinstance(
                                    loot[0], list) else loot[0], count)
                            lootMsg.append(ritem.name)
                            ret = corpse.placeItemRecursive(ritem)

                    if ret == None:
                        log.msg(
                            "Warning: Monster '%s' extends all possible loot space"
                            % self.data['name'])
                        break

        else:
            corpse = None

        scriptsystem.get("death").runSync(
            self,
            self.getLastDamager() if self.lastDamagers else None,
            corpse=corpse)
        if self.alive or self.data["health"] > 0:
            print "[May bug] Death events brought us back to life?"
            return

        # Remove bpth small and full splashes on the tile.
        for item in tile.getItems():
            if item.itemId in SMALLSPLASHES or item.itemId in FULLSPLASHES:
                tile.removeItem(item)

        # Add full splash
        splash = Item(FULLSPLASH)
        splash.fluidSource = self.base.blood

        if corpse:
            corpse.place(self.position)
        splash.place(self.position)

        # Start decay
        if corpse:
            corpse.decay()
        splash.decay()

        # Remove me. This also refresh the tile.
        self.remove()

        if not isSummon and self.lastDamagers and self.getLastDamager(
        ).isPlayer() and self.getLastDamager() != self.master:
            if lootMsg:
                self.getLastDamager().message(
                    _l(self.getLastDamager(), "loot of %(who)s: %(loot)s") % {
                        "who": self.data["name"].lower(),
                        "loot": ', '.join(lootMsg)
                    }, MSG_LOOT)
            else:
                self.getLastDamager().message(
                    _l(self.getLastDamager(), "loot of %s: nothing") %
                    (self.data["name"]), MSG_LOOT)

            # Experience split.
            attackerParty = self.getLastDamager().party()
            if attackerParty and attackerParty.shareExperience and attackerParty.checkShareExperience(
            ):
                for member in attackerParty.members:
                    if member.data["stamina"] or config.noStaminaNoExp == False:
                        exp = (self.base.experience /
                               len(attackerParty.members)
                               ) * config.partyExperienceFactor
                        member.modifyExperience(exp *
                                                member.getExperienceRate())

                        if exp >= member.data["level"]:
                            member.soulGain()
            else:
                if self.getLastDamager(
                ).data["stamina"] or config.noStaminaNoExp == False:
                    self.getLastDamager().modifyExperience(
                        self.base.experience *
                        self.getLastDamager().getExperienceRate())

                    if self.base.experience >= self.getLastDamager(
                    ).data["level"]:
                        self.getLastDamager().soulGain()

        # Begin respawn
        if self.respawn:
            self.position = self.spawnPosition
            self.target = None
            self.targetMode = 0
            if self.spawnTime != 0:
                if self.spawnTime:
                    reactor.callLater(self.spawnTime,
                                      self.base.spawn,
                                      self.spawnPosition,
                                      spawnTime=self.spawnTime,
                                      spawnDelay=0,
                                      check=False)
                else:
                    return
            else:
                reactor.callLater(self.base.spawnTime,
                                  self.base.spawn,
                                  self.spawnPosition,
                                  spawnDelay=0,
                                  check=False)