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ę

monster.cpp
void Monster::dropLoot(Container* corpse)

na:

monster.cpp
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:

player.cpp
void Player::dropLoot(Container* corpse)
{
	if(!corpse || lootDrop != LOOT_DROP_FULL)
		return;

i pod tym doklejamy:

player.cpp
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:

creatureevent.h
uint32_t executeKill(Creature* creature, Creature* target, const DeathEntry& entry);

I pod tym doklejamy:

creatureevent.h
uint32_t executeDropLoot(Creature* creature, Container* corpse);

Otwieramy creatureevent.cpp i szukamy:

creatureevent.cpp
uint32_t CreatureEvent::executeKill(Creature* creature, Creature* target, const DeathEntry& entry)

i pod całym blokiem tej funkcji doklejamy:

creatureevent.cpp
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:

creatureevent.cpp
else if(tmpStr == "kill")
		m_type = CREATURE_EVENT_KILL;

i pod tym doklejamy:

creatureevent.cpp
else if(tmpStr == "droploot")
        m_type = CREATURE_EVENT_DROP_LOOT;
 

Szukamy

creatureevent.cpp
case CREATURE_EVENT_KILL:
			return "onKill";

i pod tym doklejamy:

creatureevent.cpp
case CREATURE_EVENT_DROP_LOOT:
            return "onDropLoot";

Szukamy:

creatureevent.cpp
case CREATURE_EVENT_LOGIN:
			return "cid";

i pod tym doklejamy:

creatureevent.cpp
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

onDropLoot.cpp
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

otspub/ondroploot_event.txt · Last modified: 2011/04/14 19:58 by karpio
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki