Autor: Karpio
Testowane na: The Forgotten Server 0.4_DEV.r4086
onDropLoot, jest to funkcja do creaturescripts wykonywana w momencie losowania loota :D
A więc zaczynamy
Otwieramy plik monster.cpp
i zamieniamy całą funkcję
void Monster::dropLoot(Container* corpse)
na:
void Monster::dropLoot(Container* corpse) { bool status = true; CreatureEventList dropLootEvents = getCreatureEvents(CREATURE_EVENT_DROP_LOOT); for(CreatureEventList::iterator it = dropLootEvents.begin(); it != dropLootEvents.end(); ++it) if(!(*it)->executeDropLoot(this, corpse) && status) status = false; if(!status) return; if(corpse && lootDrop == LOOT_DROP_FULL) mType->dropLoot(corpse); }
Dalej otwieramy player.cpp, szukamy:
void Player::dropLoot(Container* corpse) { if(!corpse || lootDrop != LOOT_DROP_FULL) return;
i pod tym doklejamy:
bool status = true; CreatureEventList dropLootEvents = getCreatureEvents(CREATURE_EVENT_DROP_LOOT); for(CreatureEventList::iterator it = dropLootEvents.begin(); it != dropLootEvents.end(); ++it) if(!(*it)->executeDropLoot(this, corpse) && status) status = false; if(!status) return;
Otwieramy creatureevent.h
Szukamy: CREATURE_EVENT_KILL,
i pod tym doklejamy:
CREATURE_EVENT_DROP_LOOT,
Szukamy:
uint32_t executeKill(Creature* creature, Creature* target, const DeathEntry& entry);
I pod tym doklejamy:
uint32_t executeDropLoot(Creature* creature, Container* corpse);
Otwieramy creatureevent.cpp i szukamy:
uint32_t CreatureEvent::executeKill(Creature* creature, Creature* target, const DeathEntry& entry)
i pod całym blokiem tej funkcji doklejamy:
uint32_t CreatureEvent::executeDropLoot(Creature* creature, Container* corpse) { //onDropLoot(cid, corpse) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; scriptstream << "local corpse = " << env->addThing(corpse) << std::endl; scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ std::stringstream desc; desc << player->getName(); env->setEventDesc(desc.str()); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); lua_pushnumber(L, env->addThing(corpse)); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::cout << "[Error - CreatureEvent::executeDropLoot] Call stack overflow." << std::endl; return 0; } }
Szukamy:
else if(tmpStr == "kill") m_type = CREATURE_EVENT_KILL;
i pod tym doklejamy:
else if(tmpStr == "droploot") m_type = CREATURE_EVENT_DROP_LOOT;
Szukamy
case CREATURE_EVENT_KILL: return "onKill";
i pod tym doklejamy:
case CREATURE_EVENT_DROP_LOOT: return "onDropLoot";
Szukamy:
case CREATURE_EVENT_LOGIN: return "cid";
i pod tym doklejamy:
case CREATURE_EVENT_DROP_LOOT: return "cid, corpse";
Zapisujemy i kompilujemy i to na tyle :)
Przykładowe użycie:
Do data/creaturescripts/scripts dodajemy plik onDropLoot.lua
function onDropLoot(cid, corpse) if(getCreatureName(cid):lower() == "demon" and isMonster(cid)) then if(math.random(1,5) == 1) then doAddContainerItem(corpse, 9932) -- add firewalker boots to loot end end return true end
Plik data/creaturescripts/creaturescripts.xml:
<creatureevent type="droploot" name="onDropLoot" event="script" value="onDropLoot.lua"/>
Plik data/creaturescripts/scripts/kill.lua po function onKill() doklejamy:
registerCreatureEvent(target, "onDropLoot")
Skrypt sprawi, że jeśli zabijemy demca to mamy 20% szansy, że do loota doda nam firewalker boots.
Wiem, że się zaraz zapytacie, po co to skoro można ustawić szanse w pliku xml monstera.
Odpowiedź:
A no po to, że dzięki temu możemy też ustawiać, losowe statystyki dla loota, oraz locić przedmioty z określonym aid (np. klucze xD).
PS. w skrypcie LUA return false spowoduje, że nie pojawi się nawet ciało po zgonie więc radzę uważać :P