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
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
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)
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)