EOSERV Forum > EOSERV > Map Effects - Release
Topic is locked.
Page: << 1 >>
Map Effects - Release
Author Message
Post #29235 Map Effects - Release

It's just something that I have created. It requires you to create a effects.ini, that comes with a format. I will give you a step by step instructions on how to add it, and if any errors occur, you may report to me. Any mistakes that you find, it'd be very much helpfulifyoupostedthemheresoIcould fix them. It was created on Revision 176, and I think anything above it SHOULD work. Most of this can be copy and pasted simply into your source, and I will even try to advise you where to place it.

No credit is required, but I wouldn't suggest "stealing" it as your own. Apollo helped me with the .ini, and with some of the testing.

Effects.ini - this is to give you the format, and some examples


# Map Effects information
#
# Format:
#  id.type = (hpdrain|tpdrain|quake)
#  id.time = {time} or {mintime, maxtime}
#  if hpdrain or tpdrain
#      id.percent = {percent} or {minpercent, maxpercent} 
#  else
#      id.range = {range} or {minrange, maxrange}
#
# Example:
#  1.type = hpdrain
#  1.time = 40,60
#  1.percent = 10, 15
#
# Creates the map effect number 1, which drains hp, and happens between 40 to 60 seconds.
# It takes 10 to 15 percent of health away each time it reaches that time.
#
# These id's can be edited in the map's EMF format under byte 20, the map effect.
#
# It is recommended to create a new file and change the config to point at it
# rather than editing this file.
#

1.type = hpdrain
1.time = 15
1.percent = 10

2.type = tpdrain
2.time = 15
2.percent = 10

3.type = quake
3.time = 20,60
3.range = 0,1

4.type = quake
4.time = 30,60
4.range = 0,2

5.type = quake
5.time = 10,50
5.range = 3,5

6.type = quake
6.time = 5,20
6.range = 6,8

Config.ini - Best to be right after the ArenasFile, to keep order

## EffectsFile (string)
# File containing the map effect data
EffectsFile = ./data/effects.ini

Packet.hpp - Must be in PacketAction, Best if it's right after 27, to keep order

PACKET_HPEFFECT = 31,

World.hpp - Best if right after Config arenas_config; to keep order

Config effects_config;

Map.hpp

unsigned char effect;

double last_effect;
int effect_interval;

void DrainHP(int percent);
void DrainTP(int percent);

Main.cpp - This isn't required, but it gets rid of the warning in your server. If added, must be placed in main, best if right after arenas, to keep order

eoserv_config_default(config, "EffectsFile"         , "./data/effects.ini");

Packet.cpp - MUST be placed under std::string PacketProcessor::GetActionName
but best if it comes right after case PACKET_GET, to keep order

case PACKET_HPEFFECT: return "HPEffect";

World.cpp

This MUST be placed at the top, at least above World::World.
void world_map_effect(void *world_void)
{
    World *world(static_cast<World *>(world_void));

    double current_time = Timer::GetTime();
    UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
    {
        if (map->last_effect + double(map->effect_interval) < current_time)
        {
            std::string type = util::lowercase(world->effects_config[util::to_string(map->effect) + ".type"]);
            int param = 0, new_interval = 0;
            std::vector<std::string> parts = util::explode(',', world->effects_config[util::to_string(map->effect) + (type == "quake" ? ".range" : ".percent")]);
            if (parts.size() > 1)
            {
                if (parts.size() != 2)
                {
                    Console::Err("WARNING: skipping invalid effects data in ID %i", map->effect);
                    return;
                }
                else
                {
                    param = util::rand(util::tdparse(parts[0]), util::tdparse(parts[1]));
                }
            }
            else
            {
                param = static_cast<int>(world->effects_config[util::to_string(map->effect) + (type == "quake" ? ".range" : ".percent")]);
            }

            parts = util::explode(',', world->effects_config[util::to_string(map->effect) + ".time"]);
            if (parts.size() > 1)
            {
                if (parts.size() != 2)
                {
                    Console::Err("WARNING: skipping invalid effects data for ID %i", map->effect);
                }
                else
                {
                    new_interval = util::rand(util::tdparse(parts[0]), util::tdparse(parts[1]));
                }
            }

            if (type == "hpdrain")
            {
                map->DrainHP(param);
            }
            else if (type == "tpdrain")
            {
                map->DrainTP(param);
            }
            else if (type == "quake")
            {
                map->Effect(1, param);
            }

            map->last_effect = Timer::GetTime();
            if (new_interval > 0) map->effect_interval = new_interval;
        }
    }
}

This MUST be placed in World::World, best if under the arena config, to keep order

try
{
        this->effects_config.Read(static_cast<std::string>(this->config["EffectsFile"]));
}
catch (std::runtime_error)
{
        Console::Err("Could not load %s", static_cast<std::string>(this->config["EffectsFile"]).c_str());
}

This MUST be placed in World::World, best if under the rest of the timers, to keep order
event = new TimeEvent(world_map_effect, this, 1.0, Timer::FOREVER);
this->timer.Register(event);
event->Release();

Map.cpp

This must be placed in Map::Load, right after "this->pk = etc"
SAFE_SEEK(fh, 0x20, SEEK_SET);
SAFE_READ(buf, sizeof(char), 1, fh);
this->effect = PacketProcessor::Number(buf[0]);

This must be placed in Map::Map, BELOW this->Load();
this->last_effect = Timer::GetTime();
std::vector<std::string> parts = util::explode(',', this->world->effects_config[util::to_string(this->effect) + ".time"]);
    if (parts.size() > 1)
    {
        if (parts.size() != 2)
        {
            Console::Err("WARNING: skipping invalid effects data for ID %i", this->effect);
        }
        else
        {
            this->effect_interval = util::rand(util::tdparse(parts[0]), util::tdparse(parts[1]));
        }
    }
    else
    {
        this->effect_interval = static_cast<int>(this->world->effects_config[util::to_string(this->effect) + ".time"]);
}

Place this wherever
void Map::DrainHP(int percent)
{
    PacketBuilder builder;

    UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
    {
        int drain = std::floor(character->hp / percent);
        if (character->hp <= drain)
        {
            drain = character->hp - 1;
        }
        character->hp -= drain;

        builder.SetID(PACKET_EFFECT, PACKET_HPEFFECT);
        builder.AddShort(limitamount);
        builder.AddShort(character->hp);
        builder.AddShort(character->maxhp);
        UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
        {
               if (character->InRange(checkchar)
               {
                      drain = std::floor(checkchar->hp / percent);
                      if (checkchar->hp <= drain)
                      {
                             drain = checkchar->hp - 1;
                      }

                      builder.AddShort(checkchar->player->id);
                      builder.AddChar(int(double(checkchar->hp) / double(checkchar->maxhp) * 100.0));
                      builder.AddShort(drain);
               }
        }
        character->player->client->SendBuilder(builder);
        builder.Reset();
    }
}

void Map::DrainTP(int percent)
{
    PacketBuilder builder;

    UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
    {
        int limitamount = std::floor(character->tp / percent);

        character->tp -= limitamount;

        builder.SetID(PACKET_EFFECT, PACKET_SPEC);
        builder.AddChar(1);
        builder.AddShort(limitamount);
        builder.AddShort(character->tp);
        builder.AddShort(character->maxtp);
        character->player->client->SendBuilder(builder);
        builder.Reset();
    }
}
---
http://www.addipop.com
14 years, 22 weeks ago
Post #29265 Re: Map Effects - Release

Nice release, and unique. Why didnt you make it read the map data instead though?

14 years, 22 weeks ago
Post #29299 Re: Map Effects - Release
DellKid posted: (3rd Jan 2010 09:50 am)

Nice release, and unique. Why didnt you make it read the map data instead though?



hmm... what is this?

Edit: Addison, I experience strange TP Drain (doesn't drain visually on map). HP drain with two players on the map seems to call the 2nd players health and send to both players (resulted in xx/10 on both players in HP drain, min/max breaks for 1st player). Leaving test server up for you on SLN to see a visual *Testing Map Effects.

This must be placed in Map::Load, right after "this->pk = etc"
SAFE_SEEK(fh, 0x20, SEEK_SET);
SAFE_READ(buf, sizeof(char), 1, fh);
this->effect = PacketProcessor::Number(buf[0]);

14 years, 21 weeks ago
Post #29322 Re: Map Effects - Release

Map type effects, instead of cheaply configurating each map..

14 years, 21 weeks ago
Post #29323 Re: Map Effects - Release
DellKid posted: (3rd Jan 2010 05:38 pm)

Map type effects, instead of cheaply configurating each map..


Go for it.
---
Web developer, currently looking for graphic artists / designers.
14 years, 21 weeks ago
Post #29386 Re: Map Effects - Release

Fixed.

14 years, 21 weeks ago
Page: << 1 >>
Topic is locked.
EOSERV Forum > EOSERV > Map Effects - Release