Postado Dezembro 9, 2020 4 anos Quando o duelo é iniciado contra o NPC (ginásio, aleatório, missão) não consigo dar target no Pokémon do NPC, e as skills também não dão dano. Já o pokemon do NPC pode me atacar e matar normalmente. Segue meu script abaixo: Spoiler -- Last Storages: 9312, 9712 if (NpcBattle == nil) then local NPC_BATTLE_TIMEOUT = 60 -- one minute local NPC_TIME_BETWEEN_BATTLES = 23 * 60 * 60 -- 24 hours local NPC_TIME_BETWEEN_BATTLES_FOREVER = -2 local NPC_DIFFICULTY_DYNAMIC = 0 -- Depends on player level local NPC_POKEMON_EXPERIENCE_RATE = 2.0 --local NPC_LEVEL_STORAGE_BASE = 9500 -- Just to remind local NPC_LEVEL_MAX = 100 local NPC_GROW_PER_LEVEL = 3 -- How much the NPC Pokemon will grow with each NPC level --local LAST_BATTLE_TIME_STORAGE_BASE = 9100 -- Just to remind local STORAGE_BASE = 9000 local NPC_STORAGES = { CURRENT_BATTLE_STATUS = STORAGE_BASE + 1, OPPONENT = STORAGE_BASE + 2, POKEMON1_STATUS = STORAGE_BASE + 3, POKEMON2_STATUS = STORAGE_BASE + 4, POKEMON3_STATUS = STORAGE_BASE + 5, POKEMON4_STATUS = STORAGE_BASE + 6, POKEMON5_STATUS = STORAGE_BASE + 7, POKEMON6_STATUS = STORAGE_BASE + 8, BATTLE_TIMEOUT = STORAGE_BASE + 9 } local POKEMONNUMBER_TO_VAR = { [1] = NPC_STORAGES.POKEMON1_STATUS, [2] = NPC_STORAGES.POKEMON2_STATUS, [3] = NPC_STORAGES.POKEMON3_STATUS, [4] = NPC_STORAGES.POKEMON4_STATUS, [5] = NPC_STORAGES.POKEMON5_STATUS, [6] = NPC_STORAGES.POKEMON6_STATUS } local NPC_BATTLE_STATUS = { ISNT_BATTLEING = -1, IS_BATTLEING = 0 } local NPC_POKEMON_STATUS = { CANNOT_USE = -1, CAN_USE = 0 } local TALK_STATE = { ERASE = 0, ACCEPTING_BATTLE = 1 } local BATTLE_END_MODES = { PLAYER_LOGOUT = 0, PLAYER_WIN = 1, PLAYER_LOSS = 2, PLAYER_AWAY = 3 } local NPC_DIALOGS = { POKEMON_DOWN = { "Grr...", "I guess I underestimated you...", "So you aren't so weak.", "Let's see if you can beat this" }, BATTLE_START = { "Alright, prepare yourself!", "Yep! Let's battle!", "Let's see if you can do." }, PLAYER_WITHOUT_POKEMON = { "Where is your Pokemon?", "Where is your Pokemon? Afraid?", "First call your Pokemon!" }, NPC_LOSS = { "Grr...", "You're very lucky...", "Congratulations!" }, NPC_WIN = { "Haha! Where is the Pokemon trainer?", "Yes! I'm the best! No chance for you.", "More luck next time." } } --[[ // ]] local NpcsByName = {} NpcBattle = { name = "", uid = 0, pokemons = {}, currentPokemons = {}, rewardBaseExp = 0, rewardItems = {}, rewardUniqueItems = {}, rewardRespect = 0, rewardBadge = nil, lastBattleTimeStorage = 0, requiredRespect = 0, oneWin = false, difficulty = 10, required = nil, onWin = nil, cooldowns = {}, levelStorage = 0, baseBet = 0, currentBet = 0, npcHandler = nil, requiredLevel = 0, changes = {}, -- new pokemon that the NPC will carry when the player win x times structure = changes{{level = 1, pokemon = "Pikachu"}, {level = 2, pokemon = Charmander}, ...} payRespect = 0, evolve = true, lastDefeatTimeStorage = nil, lastOrder = 0, pokemonMaxLevel = NPC_LEVEL_MAX, specialMove = nil, -- A move that all Pokemon from this NPC will use pokemonDefeatExperienced = false, onEnd = nil, onDefeatNpcPokemon = nil, requiredMessage = nil, pokemonMovesets = nil, currentPokemonId = -1, pokemonTeamEvolvable = true, extraStats = nil, lossSpeech = nil, winSpeech = nil, battleInterval = nil, defeatedPokemonCount = 0, linealOrder = false } -- local REGISTERED_STORAGES = {} function NpcBattle:new(name, lastBattleTimeStorage, levelStorage, npcHandler, lastDefeatTimeStorage) if (not npcHandler) then log(LOG_TYPES.ERROR, "NpcBattle:new missing npcHandler", name, lastBattleTimeStorage, levelStorage) return end if (not levelStorage) then log(LOG_TYPES.ERROR, "NpcBattle:new missing levelStorage", name, lastBattleTimeStorage) return end if (not lastBattleTimeStorage) then log(LOG_TYPES.ERROR, "NpcBattle:new missing lastBattleTimeStorage", name) return end if (not name or type(name) ~= "string") then log(LOG_TYPES.ERROR, "NpcBattle:new missing name") return end --[[if (table.find(REGISTERED_STORAGES, lastBattleTimeStorage)) then This is buggy, cuz if we put more then one NPC at the map (same NPC) the warning will show up log(LOG_TYPES.ERROR, "NpcBattle:new duplicated last battle time storage", name, lastBattleTimeStorage) else REGISTERED_STORAGES[#REGISTERED_STORAGES + 1] = lastBattleTimeStorage end if (table.find(REGISTERED_STORAGES, levelStorage)) then log(LOG_TYPES.ERROR, "NpcBattle:new duplicated level storage", name, levelStorage) else REGISTERED_STORAGES[#REGISTERED_STORAGES + 1] = levelStorage end]] local obj = {} obj.name = name obj.lastBattleTimeStorage = lastBattleTimeStorage obj.levelStorage = levelStorage obj.npcHandler = npcHandler obj.lastDefeatTimeStorage = lastDefeatTimeStorage setmetatable(obj, self) self.__index = self NpcsByName[name] = obj if (getCreatureIcon(getNpcId()) == CREATURE_ICONS.NONE) then setCreatureIcon(getNpcId(), CREATURE_ICONS.BATTLE) end return obj end function NpcBattle:setBattleInterval(v) self.battleInterval = v end function NpcBattle:setCustomPokemonLevel(v) self.customPokemonLevel = v end function NpcBattle:setLossSpeech(v) self.lossSpeech = v end function NpcBattle:setWinSpeech(v) self.winSpeech = v end function NpcBattle:setPokemonMovesets(movesets) self.pokemonMovesets = movesets end function NpcBattle:setPokemons(pokemons) self.pokemons = pokemons end function NpcBattle:setRewardBaseExp(rewardBaseExp) self.rewardBaseExp = rewardBaseExp end function NpcBattle:setRewardItems(rewardItems) self.rewardItems = rewardItems end function NpcBattle:setRewardUniqueItems(rewardUniqueItems) self.rewardUniqueItems = rewardUniqueItems end function NpcBattle:setRewardRespect(rewardRespect) self.rewardRespect = rewardRespect end function NpcBattle:setRewardBadge(rewardBadge) self.rewardBadge = rewardBadge end function NpcBattle:setRequiredRespect(requiredRespect) self.requiredRespect = requiredRespect end function NpcBattle:setOneWin(oneWin) self.oneWin = oneWin end function NpcBattle:setDifficulty(difficulty) self.difficulty = difficulty end function NpcBattle:setRequired(required) self.required = required end function NpcBattle:setRequiredMessage(msg) self.requiredMessage = msg end function NpcBattle:setOnWin(onWin) self.onWin = onWin end function NpcBattle:setOnEnd(v) self.onEnd = v end function NpcBattle:setOnDefeatNpcPokemon(v) self.onDefeatNpcPokemon = v end function NpcBattle:setBaseBet(baseBet) self.baseBet = baseBet end function NpcBattle:setRequiredLevel(requiredLevel) self.requiredLevel = requiredLevel end function NpcBattle:addChange(level, pokemon) table.insert(self.changes, { level = level, pokemon = pokemon }) end function NpcBattle:setPayRespect(payRespect) self.payRespect = payRespect end function NpcBattle:setEvolve(evolve) self.evolve = evolve end function NpcBattle:setPokemonMaxLevel(v) self.pokemonMaxLevel = v end function NpcBattle:setSpecialMove(v) self.specialMove = v end function NpcBattle:setPokemonDefeatExperienced(v) self.pokemonDefeatExperienced = v end function NpcBattle:setRequiredStorage(v) self.requiredStorage = v end function NpcBattle:setPokemonTeamEvolvable(v) self.pokemonTeamEvolvable = v end function NpcBattle:setPokemonExtraStats(v) self.extraStats = v end function NpcBattle:setLinealOrder(v) self.linealOrder = v end --[[ // ]] -- IS function NpcBattle:isBattleing() return getCreatureStorage(self.uid, NPC_STORAGES.CURRENT_BATTLE_STATUS) == NPC_BATTLE_STATUS.IS_BATTLEING end function NpcBattle:isPokemonOnline() return #getCreatureSummons(self.uid) > 0 end -- GET function NpcBattle:getPokemons() return self.pokemons end function NpcBattle:getPokemon() return getCreatureSummons(self.uid)[1] end function NpcBattle:getBattleTimeoutRemaing() return getCreatureStorage(self.uid, NPC_STORAGES.BATTLE_TIMEOUT) end function NpcBattle:getRequiredRespect() return self.requiredRespect end function NpcBattle:getMoveCooldown(move) return (self.cooldowns[move] and self.cooldowns[move] - getCurrentTimeInSeconds()) or 0 end --[[ The NPC level is based on how many wins the player gets against him, many wins = npc stronger ]] function NpcBattle:getLevel(pid) if (self.evolve) then local v = getCreatureStorage(pid, self.levelStorage) return (v and v > 0 and v <= self.pokemonMaxLevel) and v or 1 end return 1 end function NpcBattle:getPokemonMove(pokemonUid, targetUid) local moves = self.pokemonMovesets and self.pokemonMovesets[self.currentPokemonId] or getPokemonDefaultSkills(getPokemonReferenceName(pokemonUid)) if (self.specialMove) then moves[#moves + 1] = self.specialMove end -- First try a random move, if cant use it, try from the strongest to down local move = table.random(moves) if (not self:canPokemonUseMove(move, pokemonUid, targetUid)) then move = nil for i = #moves, #moves, -1 do if (self:canPokemonUseMove(moves[i], pokemonUid, targetUid)) then move = moves[i] break end end end return move end -- SET function NpcBattle:setBattleStatus(status) doCreatureSetStorage(self.uid, NPC_STORAGES.CURRENT_BATTLE_STATUS, status) end function NpcBattle:setOpponent(opponent) doCreatureSetStorage(self.uid, NPC_STORAGES.OPPONENT, opponent) doNpcSetOpponent(self.uid, opponent) -- Source function end function NpcBattle:setPokemonStatus(pokemonNumber, status) doCreatureSetStorage(self.uid, POKEMONNUMBER_TO_VAR[pokemonNumber], status) end function NpcBattle:setBattleTimeout(battleTimeout) doCreatureSetStorage(self.uid, NPC_STORAGES.BATTLE_TIMEOUT, battleTimeout) end function NpcBattle:setPlayerLastBattleTimeWithNpc(pid, forever) if (isNumber(forever)) then doCreatureSetStorage(pid, self.lastBattleTimeStorage, forever) else doCreatureSetStorage(pid, self.lastBattleTimeStorage, (forever and NPC_TIME_BETWEEN_BATTLES_FOREVER or os.time())) end end function NpcBattle:setMoveCooldown(move, cooldown) if (not cooldown) then cooldown = getPokemonSkillCooldownTime(move) end self.cooldowns[move] = cooldown + getCurrentTimeInSeconds() end function NpcBattle:setLevel(pid, level) doCreatureSetStorage(pid, self.levelStorage, (level <= self.pokemonMaxLevel and level or self.pokemonMaxLevel)) end -- CAN function NpcBattle:canPokemonUseMove(move, pokemonUid, targetUid) if (self:getMoveCooldown(move) > 0 or getPokemonSkillWildBlock(move) or getMonsterLevel(pokemonUid) < getPokemonSkillRequiredLevel(getCreatureName(pokemonUid), move) or (getPokemonSkillMakeHeal(move) and getCreatureHealth(pokemonUid) / getCreatureMaxHealth(pokemonUid) > 0.5)) then return false end if (getInstantSpellInfo(SKILL_FUNCTION_PREFIX .. move).needdirection == 1) then local pokemonPos, targetPos = getCreaturePosition(pokemonUid), getCreaturePosition(targetUid) if (pokemonPos.x ~= targetPos.x and pokemonPos.y ~= targetPos.y) then return false end doCreatureSetLookDirection(pokemonUid, getDirectionTo(pokemonPos, targetPos)) end return true end function NpcBattle:canPlayerBattleWithNpc(pid) if (getPlayerDueling(pid)) then return __L(pid, "You can't battle against me while you're dueling.") end if (self.payRespect > 0 and getPlayerRespect(pid) < self.payRespect) then return string.format(__L(pid, "You need pay %s respect points to battle against me."), self.payRespect) end if (getPlayerLevel(pid) < self.requiredLevel) then return string.format(__L(pid, "You need at least level %s to battle against me."), self.requiredLevel) end self:doUpdateCurrentBet(pid) if (self.currentBet > 0 and getPlayerMoney(pid) < self.currentBet) then return string.format(__L(pid, "You need at least %s dollars to bet."), self.currentBet) end if (getPlayerRespect(pid) < self.requiredRespect) then return string.format(__L(pid, "Sorry kid, you need at least %s respect points to do a battle with me."), self.requiredRespect) end if (self.rewardBadge ~= nil) then if (getPlayerItemCount(pid, self.rewardBadge.newItemId) > 0) then return __L(pid, "You already have my badge, there is no reason to a new battle.") end end local lastBattleTime = getCreatureStorage(pid, self.lastBattleTimeStorage) if (lastBattleTime == NPC_TIME_BETWEEN_BATTLES_FOREVER) then return __L(pid, "You beat me before, there is no reason to a new battle.") elseif (lastBattleTime > -1) then local interval = self.battleInterval ~= nil and self.battleInterval or NPC_TIME_BETWEEN_BATTLES -- If default 24h, we can disable the remaing time if the player dueled before the serversave if (interval == NPC_TIME_BETWEEN_BATTLES and lastBattleTime <= getGlobalStorageValue(GLOBAL_STORAGES.SERVER_START_TIME)) then interval = 0 end local remaingTime = (lastBattleTime + interval) - os.time() if (remaingTime > 0) then return string.format(__L(pid, "Sorry, you must wait %s seconds to battle with me again."), table.concat(string.timediff(remaingTime, pid))) end end if ((self.requiredStorage and getCreatureStorage(pid, self.requiredStorage) < 0) or (self.required and not self.required(pid))) then return self.requiredMessage and self.requiredMessage or __L(pid, "You can't duel against me yet.") end if (not isSightClear(getCreaturePosition(pid), getCreaturePosition(self.uid), false)) then return __L(pid, "First get next to me.") end if (isPokemonOnline(pid)) then local pokemon = getPlayerPokemon(pid) if (isMonster(pokemon) and isPokemonUsingHealthPotion(pokemon) or isPokemonUsingEnergyPotion(pokemon)) then return __L(pid, "You can't battle against me while your Pokemon is using potions.") end end if (getTilePzInfo(getCreaturePosition(pid))) then return __L(pid, "You can't duel against me while you are in a protection zone.") end return true end -- DO function NpcBattle:doMovesCooldownReset() self.cooldowns = {} end function NpcBattle:doPlayerGiveBadge(pid, badge) doTransformItem(getPlayerItemById(pid, true, badge.oldItemId).uid, badge.newItemId) end function NpcBattle:doPokemonsStatusReset() for i = 1, #self.currentPokemons do self:setPokemonStatus(i, NPC_POKEMON_STATUS.CAN_USE) end end function NpcBattle:doBattleTimeoutReset() self:setBattleTimeout(NPC_BATTLE_TIMEOUT) end function NpcBattle:doCallPokemon(pokemonName, pid) self:doMovesCooldownReset() doAddExhaust(self.uid) local spawnPosition = getCreaturePosition(self.uid) local pokemon = doSummonCreature(pokemonName, spawnPosition, false) local pos = getPositionAdjacent(pokemon, spawnPosition) if (pos) then doTeleportThing(pokemon, pos) end doConvinceCreature(self.uid, pokemon) doSendMagicEffect(spawnPosition, balls["poke"].effects.use) registerCreatureEvent(pokemon, "npcPokemonDeath") doCreatureSay(self.uid, string.format(__L(pid, "Go, %s!"), pokemonName), TALKTYPE_MONSTER) addEvent(function() if (isCreature(pokemon)) then doSendCreatureEffect(pokemon, CREATURE_EFFECTS.RED_FADE_IN) end end, 10) local level = 0 if (self.customPokemonLevel ~= nil) then level = self.customPokemonLevel(pid) elseif (self.difficulty ~= NPC_DIFFICULTY_DYNAMIC) then level = self.difficulty + ((self:getLevel(getNpcOpponent(self.uid)) - 1) * NPC_GROW_PER_LEVEL) else level = getPlayerLevel(getNpcOpponent(self.uid)) level = level >= 10 and level or 10 level = level <= 90 and level or 90 level = getRandom(level - 20, level) end level = (level <= self.pokemonMaxLevel and level or self.pokemonMaxLevel) level = (level <= POKEMON_LEVEL_MAX and level or POKEMON_LEVEL_MAX) level = (level > 0 and level or 1) setMonsterExtraPoints(pokemon, level + 10) setMonsterLevel(pokemon, level) if (self.pokemonDefeatExperienced) then setCreatureSkillLoss(pokemon, true) -- Enable exp setMonsterExperienceRate(pokemon, NPC_POKEMON_EXPERIENCE_RATE) end if (self.extraStats) then setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.MAXHEALTH, self.extraStats) setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.ATTACK, self.extraStats) setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.DEFENSE, self.extraStats) setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.SPECIALATTACK, self.extraStats) setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.SPECIALDEFENSE, self.extraStats) setMonsterVarPokeStat(pokemon, MONSTER_POKE_STATS.SPEED, self.extraStats) end end local function getElementMultiplerBetweenPokemons(pokemon1, pokemon2) if (not pokemon1 or not pokemon2) then return 0 end local result = 0 local pokemon1elements = getPokemonTypes(nil, pokemon1) local pokemon2elements = getPokemonTypes(nil, pokemon2) for i = 1, #pokemon1elements do for j = 1, #pokemon2elements do result = result + getElementMultipler(pokemon1elements[i], pokemon2elements[j]) end end return result end local function findMaxInTable(inTable) if (#inTable < 1) then return nil end local resultKey, resultValue, tableKey, tableValue = -1, -1, nil, nil for tableKey = 1, #inTable do tableValue = inTable[tableKey] if (tableValue > -1 and tableValue > resultValue) then resultKey = tableKey resultValue = tableValue end end if (resultValue > -1) then return resultKey end return nil end function NpcBattle:doCallNextPokemon() local pid = getNpcOpponent(self.uid) self.defeatedPokemonCount = (self.currentPokemonId and (self.defeatedPokemonCount + 1) or 0) if (self.defeatedPokemonCount > 0 and self.onDefeatNpcPokemon) then self:onDefeatNpcPokemon(pid, self.defeatedPokemonCount) end if (self.linealOrder) then if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON1_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[1], pid) self:setPokemonStatus(1, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 1 return true end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON2_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[2], pid) self:setPokemonStatus(2, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 2 return true end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON3_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[3], pid) self:setPokemonStatus(3, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 3 return true end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON4_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[4], pid) self:setPokemonStatus(4, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 4 return true end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON5_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[5], pid) self:setPokemonStatus(5, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 5 return true end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON6_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then self:doCallPokemon(self.currentPokemons[6], pid) self:setPokemonStatus(6, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = 6 return true end return false end local npcPokemonsMultiplers = {} local npcOpponentPokemonName = getPlayerPokemonName(pid) if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON1_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 1, getElementMultiplerBetweenPokemons(self.currentPokemons[1], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 1, -1) end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON2_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 2, getElementMultiplerBetweenPokemons(self.currentPokemons[2], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 2, -1) end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON3_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 3, getElementMultiplerBetweenPokemons(self.currentPokemons[3], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 3, -1) end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON4_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 4, getElementMultiplerBetweenPokemons(self.currentPokemons[4], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 4, -1) end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON5_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 5, getElementMultiplerBetweenPokemons(self.currentPokemons[5], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 5, -1) end if (getCreatureStorage(self.uid, NPC_STORAGES.POKEMON6_STATUS) == NPC_POKEMON_STATUS.CAN_USE) then table.insert(npcPokemonsMultiplers, 6, getElementMultiplerBetweenPokemons(self.currentPokemons[6], npcOpponentPokemonName)) else table.insert(npcPokemonsMultiplers, 6, -1) end local bestPokemonToUseNow = findMaxInTable(npcPokemonsMultiplers) if (bestPokemonToUseNow) then self:doCallPokemon(self.currentPokemons[bestPokemonToUseNow], pid) self:setPokemonStatus(bestPokemonToUseNow, NPC_POKEMON_STATUS.CANNOT_USE) self.currentPokemonId = bestPokemonToUseNow return true end return false end function NpcBattle:doBattleEnd(pid, battleEndMode) if (battleEndMode == BATTLE_END_MODES.PLAYER_WIN) then if (self.lossSpeech) then doCreatureSay(self.uid, __L(pid, self.lossSpeech), TALKTYPE_SAY) else doCreatureSay(self.uid, __L(pid, table.random(NPC_DIALOGS.NPC_LOSS)), TALKTYPE_SAY) end if (self.rewardBaseExp > 0 or self.rewardBadge ~= nil or #self.rewardItems > 0 or #self.rewardUniqueItems > 0 or self.currentBet > 0) then doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You won %s and received your reward."), self.name)) else doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You won %s."), self.name)) end doPlayerAddBattleWin(pid) doPlayerAddRespect(pid, (self.rewardRespect * 2)) doPlayerAddStatistic(pid, PLAYER_STATISTIC_IDS.DEFEAT_NPC, 1) local previousLevel = self:getLevel(pid) self:setLevel(pid, previousLevel + 1) if (self.rewardBaseExp > 0) then doPlayerAddExperience(pid, self.rewardBaseExp * previousLevel) doSendAnimatedText(getCreaturePosition(pid), "+EXP!", COLOR_LIGHTGREEN) end if (self.rewardBadge ~= nil) then self:doPlayerGiveBadge(pid, self.rewardBadge) doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "Congratulations! You received the %s from %s."), getItemNameById(self.rewardBadge.newItemId), self.name)) end doPlayerAchievementCheck(pid, ACHIEVEMENT_IDS.KANTO_BADGES) for i = 1, #self.rewardItems, 2 do doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You received: %s [%sx]."), getItemNameById(self.rewardItems[i]), self.rewardItems[i + 1])) doPlayerAddItem(pid, self.rewardItems[i], self.rewardItems[i + 1], true) end for i = 1, #self.rewardUniqueItems, 2 do local item = doCreateUniqueItemEx(pid, self.rewardUniqueItems[i], self.rewardUniqueItems[i + 1]) if (item) then if (doPlayerAddItemEx(pid, item, false) == RETURNVALUE_NOERROR) then doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You received: %s [%sx]."), getItemNameById(self.rewardUniqueItems[i]), self.rewardUniqueItems[i + 1])) else doPlayerAddDepotItem(pid, 0, item) doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You received: %s [%x] directly into your depot."), getItemNameById(self.rewardUniqueItems[i]), self.rewardUniqueItems[i + 1])) end else log(LOG_TYPES.ERROR, "NpcBattle:doBattleEnd - Can't create reward unique item.", getCreatureName(pid), self.rewardUniqueItems[i], self.rewardUniqueItems[i + 1]) end end if (self.currentBet > 0) then doPlayerAddMoney(pid, math.floor(self.currentBet * 2)) end if (self.oneWin) then self:setPlayerLastBattleTimeWithNpc(pid, true) end if (self.lastDefeatTimeStorage) then doCreatureSetStorage(pid, self.lastDefeatTimeStorage, os.time()) end if (self.onWin) then self.onWin(pid) end elseif (battleEndMode == BATTLE_END_MODES.PLAYER_LOSS) then if (self.winSpeech) then doCreatureSay(self.uid, __L(pid, self.winSpeech), TALKTYPE_SAY) else doCreatureSay(self.uid, __L(pid, table.random(NPC_DIALOGS.NPC_WIN)), TALKTYPE_SAY) end doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, string.format(__L(pid, "You have been defeated by %s!"), self.name)) doPlayerAddBattleLoss(pid) elseif (battleEndMode == BATTLE_END_MODES.PLAYER_AWAY) then doCreatureSay(self.uid, table.random(NPC_DIALOGS.NPC_WIN), TALKTYPE_SAY) doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, "You and your opponent were too far from each other and the battle was canceled.") doPlayerAddBattleLoss(pid) end if (self:isPokemonOnline()) then local npcPokemon = self:getPokemon() doCreatureSay(self.uid, string.format(__L(pid, "Back, %s!"), getCreatureName(npcPokemon)), TALKTYPE_SAY) doSendMagicEffect(getCreaturePosition(npcPokemon), balls["poke"].effects.use) doRemoveCreature(npcPokemon) end self:setBattleStatus(NPC_BATTLE_STATUS.ISNT_BATTLEING) self.npcHandler:releaseFocus(pid) if (isPlayer(pid)) then setPlayerBattleing(pid, false) setPlayerDisconnectAtExit(pid, true) doCreatureSetNoMove(pid, false) if (self.onEnd) then self.onEnd(pid, battleEndMode == BATTLE_END_MODES.PLAYER_WIN, self.uid) end end end function NpcBattle:doBattleCheck(pid, battleTimeRemaing, decreaseTimeout, playerLastFreeCap, checkAlivePokemon) if (not isPlayer(pid)) then self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOGOUT) return end local playerCap = getPlayerFreeCap(pid) if (playerLastFreeCap and playerCap ~= playerLastFreeCap) then doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, "You modified your Pokemon team during battle! You're out!") self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOSS) return end if (battleTimeRemaing == 0) then doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, "Your time has ended.") self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOSS) return end local playerPosition = getCreaturePosition(pid) local npcPosition = getCreaturePosition(self.uid) if (not npcPosition) then return end if (getDistanceBetween(npcPosition, playerPosition) > 6 or playerPosition.z ~= npcPosition.z) then self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_AWAY) return end if (self:isPokemonOnline()) then local playerPokemon = getPlayerPokemon(pid) if (isCreature(playerPokemon)) then local npcPokemon = self:getPokemon() if (not hasTarget(npcPokemon)) then doCreatureSetTarget(npcPokemon, playerPokemon) end if (not isExhaust(self.uid)) then local move = self:getPokemonMove(npcPokemon, playerPokemon) if (move) then self:doPokemonUseMove(npcPokemon, move) end end if (getRandom(0, 100) <= 25 or getDistanceBetween(getCreaturePosition(npcPokemon), getCreaturePosition(playerPokemon)) > 3) then self:doOrderPokemon(npcPokemon, playerPokemon, pid) end elseif (getPlayerDuelPokemonRemaing(pid) <= 0) then self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOSS) return elseif (decreaseTimeout) then if (checkAlivePokemon) then local tmpBalls = getPlayerAllBallsWithPokemon(pid) local alives = #tmpBalls if (alives < PLAYER_BALL_MAX) then -- Maybe this player hasnt six Pokemon, so the timeout is useless for _, ball in pairs(tmpBalls) do local ballName = ballsNames[ball.itemid] if (not ballName or ball.itemid == balls[ballName].discharged) then alives = alives - 1 end end if (alives <= 0) then self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOSS) return end else checkAlivePokemon = nil -- Isnt need check if the player got six Pokemon, the timeout will work fine end end local timeout = self:getBattleTimeoutRemaing() if (timeout <= 0) then doPlayerSendTextMessage(pid, MESSAGE_STATUS_CONSOLE_BLUE, "Your time has ended.") self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_LOSS) return else doSendAnimatedText(playerPosition, timeout, TEXTCOLOR_RED) self:setBattleTimeout(timeout - 1) decreaseTimeout = false end else decreaseTimeout = true end else if (self:doCallNextPokemon()) then doCreatureSay(self.uid, __L(pid, table.random(NPC_DIALOGS.POKEMON_DOWN)), TALKTYPE_SAY) else self:doBattleEnd(pid, BATTLE_END_MODES.PLAYER_WIN) return end end addEvent(self.doBattleCheck, 500, self, pid, battleTimeRemaing - 0.5, decreaseTimeout, playerCap, checkAlivePokemon) end function NpcBattle:doBattleStart(pid) self:setBattleStatus(NPC_BATTLE_STATUS.IS_BATTLEING) self:setOpponent(pid) self:doUpdateCurrentPokemons(pid) self:doPokemonsStatusReset() self:doBattleTimeoutReset() self:doCallNextPokemon() self:setPlayerLastBattleTimeWithNpc(pid) if (self.currentBet > 0) then doPlayerRemoveMoney(pid, self.currentBet) end if (self.payRespect > 0) then doPlayerAddRespect(pid, -self.payRespect) end setPlayerDuelPokemonRemaing(pid, 6) setPlayerBattleing(pid, true) doAddCondition(pid, pokemonCallDelayCondition) doCreatureSay(self.uid, __L(pid, table.random(NPC_DIALOGS.BATTLE_START)), TALKTYPE_SAY) setPlayerDisconnectAtExit(pid, false) doCreatureSetNoMove(pid, true) self:doBattleCheck(pid, 10 * 60, true, nil, true) end function NpcBattle:doPokemonUseMove(pokemonUid, move) if (doPokemonUseSkill(pokemonUid, move)) then self:setMoveCooldown(move) doAddExhaust(self.uid) end end function NpcBattle:doUpdateCurrentPokemons(pid) local npcLevel = self:getLevel(pid) self.currentPokemons = table.copy(self.pokemons) -- Add all possibly pokemons to my team for i, change in ipairs(self.changes) do if (npcLevel >= change.level) then table.insert(self.currentPokemons, change.pokemon) end end -- If I get more then I can carry, remove random while (#self.currentPokemons > 6) do table.remove(self.currentPokemons, math.random(1, #self.currentPokemons)) end -- What level my pokemons are now local level if (self.difficulty ~= NPC_DIFFICULTY_DYNAMIC) then level = self.difficulty + ((npcLevel - 1) * NPC_GROW_PER_LEVEL) level = (level <= POKEMON_LEVEL_MAX and level or POKEMON_LEVEL_MAX) else level = getPlayerLevel(pid) level = level >= 10 and level or 10 level = level <= 90 and level or 90 level = math.random(level - 5, level) end -- Evolve them, if possible if (self.pokemonTeamEvolvable) then for i = 1, #self.currentPokemons do local evolutions = getPokemonEvolutions(self.currentPokemons[i]) while (evolutions and #evolutions > 0) do local tmpEvolutions = evolutions evolutions = nil for k, v in ipairs(tmpEvolutions) do if (level >= v.requiredLevel) then self.currentPokemons[i] = v.name evolutions = getPokemonEvolutions(self.currentPokemons[i]) break end end end end end end function NpcBattle:doUpdateCurrentBet(pid) self.currentBet = self.baseBet * self:getLevel(pid) end function NpcBattle:doOrderPokemon(pokemonUid, targetUid, pid) local pos = getPositionAdjacent(pokemonUid, getCreaturePosition(targetUid)) if (pos) then if (not getPathToEx(pokemonUid, pos)) then doTeleportThing(pokemonUid, getCreaturePosition(targetUid)) return end --doCreatureWalkToPosition(pokemonUid, pos) if ((os.time() - self.lastOrder) > 4) then doCreatureSay(self.uid, string.format(__L(pid, "%s, go there!"), getCreatureNickname(pokemonUid)), TALKTYPE_MONSTER) self.lastOrder = os.time() end end end -- Global functions function NpcBattle:doTalkStart(npcUid, pid) self.uid = npcUid if (self:isBattleing()) then selfSay("I'm battling at the moment, please wait.", pid) return TALK_STATE.ERASE else local result = self:canPlayerBattleWithNpc(pid) if (result == true) then selfSay(string.format(__L(pid, "Do you really want to battle with me?%s%s"), (self.currentBet > 0 and (string.format(__L(pid, " (You will bet %s dollars)"), self.currentBet)) or ""), (self.payRespect > 0 and (string.format(__L(pid, " (You will pay %s respect points)"), self.payRespect)) or "")), pid) return TALK_STATE.ACCEPTING_BATTLE else selfSay(result, pid) return TALK_STATE.ERASE end end end function NpcBattle:doTalkEnd(npcUid, pid, talkState) self.uid = npcUid if (talkState == TALK_STATE.ACCEPTING_BATTLE) then if (self:isBattleing()) then selfSay("I'm battling at the moment, please wait.", pid) return TALK_STATE.ERASE elseif (not isPokemonOnline(pid) and #getCreatureSummons(pid) == 0) then selfSay(__L(pid, table.random(NPC_DIALOGS.PLAYER_WITHOUT_POKEMON)), pid) return TALK_STATE.ERASE else local result = self:canPlayerBattleWithNpc(pid) if (result == true) then self:doBattleStart(pid) else selfSay(result, pid) return TALK_STATE.ERASE end end else selfSay("Huh?", pid) end return TALK_STATE.ERASE end function NpcBattle:doForceBattleStart(npcUid, pid) if (self:isBattleing()) then return false end self.uid = npcUid self:doBattleStart(pid) return true end function getNpcOpponent(nid) return getCreatureStorage(nid, NPC_STORAGES.OPPONENT) end function getNpcBattleByName(name) return NpcsByName[name] end function getPlayerDefeatedNPC(cid, npcName) local r = getCreatureStorage(cid, (type(npcName) == 'string' and getNpcBattleByName(npcName).levelStorage or npcName)) -- npcName can be the storage too, because I can normaly call this function only inside NPCs return r > 1 end function getPlayerLastDefeatedNpc(cid, lastDefeatTimeStorage) return getCreatureStorage(cid, lastDefeatTimeStorage) end function doPlayerEraseDefeatedNpc(cid, npcName) if (type(npcName) ~= 'string') then log(LOG_TYPES.ERROR, "npcBattle:doPlayerEraseDefeatedNPC - npcName is not a string.", getCreatureName(cid), npcName) return end doCreatureSetStorage(cid, getNpcBattleByName(npcName).levelStorage, -1) doCreatureSetStorage(cid, getNpcBattleByName(npcName).lastBattleTimeStorage, -1) end end
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.