• 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!

Send a message if an effect appears on the screen.

The Frenesy

Member
Joined
Sep 3, 2020
Messages
32
Solutions
1
Reaction score
7
I need a script that checks in real time the effects that appear in the player's field of view, so that the character sends an orange message on the screen.

Example, if one of these effects appears on the screen, the character says something:

ENERGYAREA
= Character says "Energy"
FIREAREA = Character says "Fire"
MORTAREA = Character says "Death"

TFS 0.4

Thanks.
 
Last edited:
Solution
If the client-side error is due to playing two sound files at once, it should be possible to "single-thread" them using addEvent().

Or client-side scripting if that's possible? Server-side scripting would be a bit sensitive to variations in client-server network latency.
There is currently no function or trigger that would allow this to happen.

So it would definitely require a source edit to accomplish this.
 
Can you give me an example on which I can make changes?
Unfortunately I do not know how to do source edits.

Another person would need to show you.

However..

Maybe if you explain what you're trying to accomplish instead of the method in which you want to accomplish your goal, there might be an existing alternative way to do that which you are trying to do.
 
Unfortunately I do not know how to do source edits.

Another person would need to show you.

However..

Maybe if you explain what you're trying to accomplish instead of the method in which you want to accomplish your goal, there might be an existing alternative way to do that which you are trying to do.

I know how to compile the sources and etc, but as my area is not programming, it gets complicated.

But thanks.
 
If we knew what you wanted to accomplish you would probably get better advice.

I'm not good at source edits either but I figured out how this works on TFS 1.3 and it looks to be pretty similar on 0.4 as well, just the constant names are different. I'm pretty sure this is not what you really want but at least I learned something.

If we take your request literally, you can try adding this:
C++:
switch (type) {
    case MAGIC_EFFECT_ENERGY_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Energy", false);
        break;
    }
    case MAGIC_EFFECT_FIRE_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Fire", false);
        break;
    }
    case MAGIC_EFFECT_MORT_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Death", false);
        break;
    }
    default: {
        break;
    }
}
In this function:

I can't speak to the performance impact but it would at least get very spammy with everyone talking for every magic effect they see. 🤷‍♂️
 
If we knew what you wanted to accomplish you would probably get better advice.

I'm not good at source edits either but I figured out how this works on TFS 1.3 and it looks to be pretty similar on 0.4 as well, just the constant names are different. I'm pretty sure this is not what you really want but at least I learned something.

If we take your request literally, you can try adding this:
C++:
switch (type) {
    case MAGIC_EFFECT_ENERGY_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Energy", false);
        break;
    }
    case MAGIC_EFFECT_FIRE_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Fire", false);
        break;
    }
    case MAGIC_EFFECT_MORT_AREA: {
        g_game.internalCreatureSay(player, SPEAK_SAY, "Death", false);
        break;
    }
    default: {
        break;
    }
}
In this function:

I can't speak to the performance impact but it would at least get very spammy with everyone talking for every magic effect they see. 🤷‍♂️

This code example that you mentioned, could you do some kind of adaptation to execute this parameter in LUA?

sendScreanSound (cid, "FireDamage.wav")

This parameter above is responsible for reproducing a sound effect in OTClient/mods/Advanced Sound

If this is possible, it would be very easy to add sound to OTClient.
 
Last edited:
I'm not good at source edits either but I figured out how this works on TFS 1.3 and it looks to be pretty similar on 0.4 as well, just the constant names are different. I'm pretty sure this is not what you really want but at least I learned something.

I would like this system not to have a collective effect, but rather an individual one, where the system only has an effect within the character's field of vision.

Heyron's idea looks good. I know this sound system that he mentioned.

If this code of yours is able to reconcile with that function in LUA, it really becomes easier to put sound in OTClient.
But we have to check if it is possible to do this.

Example:

Code:
case MAGIC_EFFECT_FIRE_AREA: {
        sendScreanSound ("FireDamage.wav")
        break;
}
 
Last edited:
This code example that you mentioned, could you do some kind of adaptation to execute this parameter in LUA?

sendScreanSound (cid, "FireDamage.wav")

This parameter above is responsible for reproducing a sound effect in OTClient/mods/Advanced Sound

If this is possible, it would be very easy to add sound to OTClient.

I would like this system not to have a collective effect, but rather an individual one, where the system only has an effect within the character's field of vision.

Heyron's idea looks good. I know this sound system that he mentioned.

If this code of yours is able to reconcile with that function in LUA, it really becomes easier to put sound in OTClient.
But we have to check if it is possible to do this.

Example:

Code:
case MAGIC_EFFECT_FIRE_AREA: {
        sendScreanSound ("FireDamage.wav")
        break;
}
It's not a collective effect as in every magic effect is sent to every player, only players in view gets the magic effect. It's just that when you have several people in the same area, they can all see the magic effect, hence each of them says "Fire". Imagine hunting demons with players saying, "Fire", "Energy" all the time.

As for the sound system, this is why we ask what you want to accomplish. What you are talking about is client sided, TFS can not play sound. I guess that "sendScreanSound" sends an extended opcode or a network message to the client to instruct it of which file to play. You could figure out what it sends and send an additional message to the client, but I would probably use a client module to handle the normal opcode from the server and add the call to play sound there.

Here is a minimal example that plays the default startup music when you see a "Poff" effect (I'm not sure if the "Poff" id the same on 0.4 though):
Lua:
local sounds = {
    --[magicEffect] = "soundfile"
    [3] = "/sounds/startup.ogg",
}

function init()
    ProtocolGame.registerOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function terminate()
    ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function onMagicEffect(opcode, msg)
    local pos = msg:getPosition()
    local effectId

    if g_game.getFeature(GameMagicEffectU16) then
        effectId = msg:getU16()
    else
        effectId = msg:getU8()
    end
    
    if g_things.getThingType(effectId, ThingCategoryEffect):getId() == 0 then
        error(("invalid effect id %s"):format(tostring(effectId)))
    end

    local effect = Effect:create()
    effect:setId(effectId)
    g_map.addThing(effect, pos)

    -- Add your code here
    if sounds[effectId] then
        g_sounds.getChannel(0):play(sounds[effectId])
    end
    return true
end
 
Here is a minimal example that plays the default startup music when you see a "Poff" effect (I'm not sure if the "Poff" id the same on 0.4 though):

Could you explain to me how to configure please?

This part I did not understand very well:

Lua:
local sounds = {
    --[magicEffect] = "soundfile"
    [3] = "/sounds/startup.ogg",
}

Does each audio in the mods/Advanced Sound/Sounds need to have the same name as the effect? For example, the fire effect reproduces the file named FIREAREA.wav, correct?

Where to install this code that you posted? In the sources or in some folder on the server?
 
Last edited:
Could you explain to me how to configure please?

This part I did not understand very well:

Lua:
local sounds = {
    --[magicEffect] = "soundfile"
    [3] = "/sounds/startup.ogg",
}

Does each audio in the mods/Advanced Sound/Sounds folder have to have the effect name? For example, the fire effect reproduces the file named FIREAREA.wav, correct?
I couldn't find the constants for the magic effects in otclient. The 3 is the same as CONST_ME_POFF in TFS 1.3, the effect id, the string is the name of the audio file to play. It does not matter what the file is named, you just need to put the name of the file in the table.
If you put your sound files in data/sounds and let's say your fire sound file if named "FireDamage.wav", you would add it like this:
Lua:
local sounds {
    -- 7 = CONST_ME_FIREAREA
    [7] = "/sounds/FireDamage.wav"
}
My script has nothing to do with "Advanced sound module", it uses only the built in sound functions of otclient. As I said it is a minimal example and needs some work to be production ready. 😛
 
Where to install this code please? I really want to test it.

In fact, your code example can be a great milestone for anyone without programming knowledge to be able to put sound on OTClient, without difficulty and with easy installation.

Is the configuration I made in your code correct? The effects ID's I got from the server file at data/lib/000-constant.lua

Lua:
local sounds {
    -- 6 = CONST_ME_FIREAREA
    -- 37 = CONST_ME_ENERGYAREA
    -- 41 = CONST_ME_ICEAREA
    -- 17 = CONST_ME_MORTAREA
    -- 49 = CONST_ME_HOLYAREA
    [6] = "/sounds/FireDamage.wav"
    [37] = "/sounds/EnergyDamage.wav"
    [41] = "/sounds/IceDamage.wav"
    [17] = "/sounds/MortDamage.wav"
    [49] = "/sounds/HolyDamage.wav"
}

function init()
    ProtocolGame.registerOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function terminate()
    ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function onMagicEffect(opcode, msg)
    local pos = msg:getPosition()
    local effectId

    if g_game.getFeature(GameMagicEffectU16) then
        effectId = msg:getU16()
    else
        effectId = msg:getU8()
    end
   
    if g_things.getThingType(effectId, ThingCategoryEffect):getId() == 0 then
        error(("invalid effect id %s"):format(tostring(effectId)))
    end

    local effect = Effect:create()
    effect:setId(effectId)
    g_map.addThing(effect, pos)

    -- Add your code here
    if sounds[effectId] then
        g_sounds.getChannel(0):play(sounds[effectId])
    end
    return true
end
 
Where to install this code please? I really want to test it.

Create folder mods/game_magic_sound.
Create file game_magic_sound.otmod:
Code:
Module
  name: game_magic_sound
  description: Add sound to magic effects
  author: forgee
  website: https://github.com/edubart/otclient
  scripts: [magic]
  sandboxed: true
  autoload: true

  @onLoad: init()

  @onUnload: terminate()
Put the script in mods/game_magic_sound/magic.lua.
 
Crie mods de pasta / game_magic_sound.
Crie o arquivo game_magic_sound.otmod:
Módulo [CÓDIGO]
nome: game_magic_sound
descrição: Adicionar som a efeitos mágicos
autor: forja
site: edubart/otclient (https://github.com/edubart/otclient)
scripts: [mágica]
sandboxed: true
autoload: true

@onLoad: init ()

@onUnload: terminate () [/ CODE]
Coloque o script em mods / game_magic_sound / magic.lua.

Ocorreu um erro no terminal.

Screenshot_1.png

Screenshot_5.png

Script:
Lua:
local sounds {
    -- 6 = CONST_ME_FIREAREA
    -- 37 = CONST_ME_ENERGYAREA
    -- 41 = CONST_ME_ICEAREA
    -- 17 = CONST_ME_MORTAREA
    -- 49 = CONST_ME_HOLYAREA
    [6] = "/sounds/FireDamage.ogg"
    [37] = "/sounds/EnergyDamage.wav"
    [41] = "/sounds/IceDamage.wav"
    [17] = "/sounds/MortDamage.wav"
    [49] = "/sounds/HolyDamage.wav"
}

function init()
    ProtocolGame.registerOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function terminate()
    ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerGraphicalEffect, onMagicEffect)
end

function onMagicEffect(opcode, msg)
    local pos = msg:getPosition()
    local effectId

    if g_game.getFeature(GameMagicEffectU16) then
        effectId = msg:getU16()
    else
        effectId = msg:getU8()
    end
  
    if g_things.getThingType(effectId, ThingCategoryEffect):getId() == 0 then
        error(("invalid effect id %s"):format(tostring(effectId)))
    end

    local effect = Effect:create()
    effect:setId(effectId)
    g_map.addThing(effect, pos)

    -- Add your code here
    if sounds[effectId] then
        g_sounds.getChannel(0):play(sounds[effectId])
    end
    return true
end
 
I made a typo apparently, put a '=' after sounds on line 1. local sounds = {

Friend, I already discovered my mistake! Your code takes into account the ID's that are in the Objetic Builder, and not in the server's LIB. You are amazing, thank you for your time and your patience to teach and explain.

Unfortunately, when there are many monsters on the screen, the client closes with an error.

OTClient is not prepared to have sound, it has difficulty reproducing several different audios at the same time, when there are many monsters on the screen.

Screenshot_11.png
 
Last edited:
A suggestion:

Don't expect the sounds to work nicely if you start a second one in the middle of one that's currently being played.
Test ASAP to see what happens.
 
A suggestion:

Don't expect the sounds to work nicely if you start a second one in the middle of one that's currently being played.
Test ASAP to see what happens.

The audios I have got through the RPG Maker VX, they are super fast, last a maximum of 500 MS. The problem is the OTClient that can't handle playing different audios at the same time.

The @forgee code is different from this other mod, I mean the "Advanced Sound Mod", which has 3D audio, however it depends on the parameter sendScreanSound (cid, "FileAudio.wav") added in each Action, Spell, of the server.

The advantage of the code made by @forgee, is that the mod is much easier to configure. I just need to define the audios that each effect (ID), will play on.
 
Last edited:
@forgee, I tested your sound mod and really liked the result, playing Tibia with sound is really a very pleasant experience. However, I went through the same problem as @Heyron, the OTCliente causes an error and closes if there are small groups of monsters on the screen.

But I don't blame you. You delivered a ready code for free, thanks.
 
Back
Top