• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[OTClient + TFS] Colorize Outfit for certain time duration + simple usage.

Fresh

Quack!
Joined
Oct 21, 2009
Messages
1,837
Solutions
18
Reaction score
615
Location
Poland

[OTClient + TFS] COLORIZE OUTFIT FOR CERTAIN TIME DURATION

Preview:

(If image is not loading, please click this link.)
About:
Basically, this pieces of code colorize creature outfit for all players on screen for certain time duration.
I made this for my own idea use, just simple: If monster cast spell Rage, it colorizes his outfit on red for certain time.
I wish to share it on OTLand, so everyone can use this feature/learn from it.

Requirements:
  • TFS 1.X+ , any which handles packet sending by LUA.
  • OTClient

Possible Bugs:
Not many, but if any player will appear on screen much time after creature uses colorize outfit function, it can not see "new" creature color because player appear on screen too late after. It can be possible bug but I made this like colorize outfit for ID of creature so this situation might not happen but I haven't tested this situation.



Let's copy-and-paste guyzZ:

OTClient:
This part, handling parsing packet from server and receiving it by client.
Search similar piece of codes that this one below and paste it after in :: protocolgame.cpp
C++:
case Proto::GameServerMakeOutfitRed:
parseGameServerMakeOutfitRed(msg);
break;
protocolgame.h :: after void parseMapDescription(const InputMessagePtr& msg); :: paste:
C++:
void parseGameServerMakeOutfitRed(const InputMessagePtr& msg);
Let's add this packet-read-by-client function in protocolgame.cpp
C++:
void ProtocolGame::parseGameServerMakeOutfitRed(const InputMessagePtr& msg)
{
    uint id = msg->getU32();
    uint duration = msg->getU32();

    CreaturePtr creature = g_map.getCreatureById(id);

    if(creature)
        creature->setInstantOutfitColor(Color::red, duration);

}
Declare this packet in protocolcodes.h , after :: GameServerChangeMapAwareRange
C++:
GameServerMakeOutfitRed             = 52,
This part, is another NEW function to colorize outfit in OTClient, because existing functions colorize in strange way (one of them is just fadeIn color smoothly and stay in this color forever, in other one function, duration don't work for me, so I decided to make another one function [below]).
Add somewhere between void functions :: creature.cpp
C++:
void Creature::setInstantOutfitColor(const Color& color, int duration)
{
    if (duration > 0) {
        m_outfitColor = color;

       // This part below is need to back "from color" to normal outfit after X duration
        auto self = static_self_cast<Creature>();
        g_dispatcher.scheduleEvent([=] {
            self->setOutfitColor(Color::white, 0);
        }, duration*1000+500); // this "+500" it's to handle time with server script, you must experiment with this duration timer by your own to get all things fit in time.
    }
}
Declaring function above (in spoiler), same "place", between void functions :: creature.h
C++:
void setInstantOutfitColor(const Color& color, int duration);
Server Side:
This part, is function in LUA that sending packet from server to client with creatureID (creature that needs to be colored) and duration (how many seconds will be in new color).
Add below function in :: data/lib/core/player.lua (or somewhere else where you got similar functions to send packets via LUA)
Lua:
function Player.rageCreature(self, creatureID, duration)
    local networkMessage = NetworkMessage()
    networkMessage:addByte(0x34) -- It's packet :: 52 OTC
    networkMessage:addU32(creatureID)
    networkMessage:addU32(duration)
    networkMessage:sendToPlayer(self)
    networkMessage:delete()
    return true
end

This part, is spell that doing something like read all players (spectators) from caster screen (creature that needs to get colored) and sending them packet to color caster outfit.
Don't forget to add in spells.xml too / lol / :: data/spells/scripts/rage.lua
Lua:
local function debuffRage(cid)
    local creature = Creature(cid)
    if(not Creature(cid)) then
        return
    end
    creature:setStorageValue(STORAGE_MONSTERRAGE, -1)
    creature:getPosition():sendMagicEffect(43)
    creature:say("Huh..", TALKTYPE_MONSTER_SAY)
    return true
end

function onCastSpell(creature, var)

    local rageTime = 6 -- Rage Time duration, how many seconds will be enraged, after that time outfit returns to previous color (removes it in my case).
    local AreaX = 13 -- X axis range to whom to send the packet (monster view range)
    local AreaY = 8 -- Y axis range to whom to send the packet (monster view range)

    -- If creature already got enraged this spell must not cast again
    if creature:getStorageValue(STORAGE_MONSTERRAGE) == 1 then
        return true
    end

    -- Sending packet to all players around creature
    local spectators = Game.getSpectators(creature:getPosition(), false, true, AreaX, AreaX, AreaY, AreaY)
    if #spectators == 0 then
        return nil
    end

    for index, spectator in ipairs(spectators) do
        if spectator:getId() ~= creature then
            creatureID = creature:getId()
            -- This is usage of function that you pasted while ago in :: data/lib/core/player.lua
            spectator:rageCreature(creatureID,rageTime)
        end
    end

     local creaturePos = creature:getPosition()
     local effectPos = creature:getPosition()+Position(1,1,0)
    local target = creature:getTarget()

    creature:setNoMove(true)
    effectPos:sendMagicEffect(255)
    creature:say("You making me angry..", TALKTYPE_MONSTER_SAY)

    addEvent(function() Game.sendAnimatedText("RAGE!", creaturePos, 180) end, 200, creature.uid)

    addEvent(function()
        effectPos:sendMagicEffect(255)
        creaturePos:sendMagicEffect(2)
        creature:setStorageValue(STORAGE_MONSTERRAGE, 1)
        creature:setNoMove(false)
        addEvent(debuffRage, rageTime * 1000, creature.uid)
        end, 500, creature.uid)
   
    return true
end

Part of increasing damage if Monster got STORAGE_MONSTERRAGE you must do by yourself (onHealthChange in CreatureScripts), because I don't know if you got feature that monsters can have storages in your TFS. Basically that's all.

So basically that's all.
If you read all code carefully you will understand how to use new function to colorize outfit into red color.
If someone can upgrade this code (in OTC) that will colorize outfit to color declared and sent in packet for example: spectator:rageCreature(creatureID,rageTime,color)
I will be very glad to get, because right now I have more things to do
:p
I will make it later for sure, but now I shared this quick feature.

Hope this feature can explain something to new OT-maker's and will be helpful to anyone :)
Enjoy! Have a good day! Peace~
 
Back
Top