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