Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Allow for arbitrary buff/debuff visuals

Closes #856
  • Loading branch information...
commit 122978e487be812b79c830d6a6b95412650f367a 1 parent 9c33631
@dorkster dorkster authored
View
23 mods/fantasycore/engine/effects.txt
@@ -1,11 +1,12 @@
-# hazard settings
-frame_size=64,64
-frame_offset=32,32
-
-# shield effect
-frame_size_sh=0,0,128,128
-frame_offset_sh=64,96
-
-# vengeance effect
-frame_size_veg=0,128,64,64
-frame_offset_veg=32,32
+# hazard settings
+frame_size=64,64
+frame_offset=32,32
+
+# status effects
+id=1
+type=shield
+gfx=shield.png
+size=0,0,128,128
+offset=64,96
+frame_total=12
+ticks_per_frame=3
View
1  mods/fantasycore/powers/powers.txt
@@ -198,7 +198,6 @@ icon=11
description=Create a force field that absorbs damage
new_state=cast
requires_mp=1
-gfx=shield.png
sfx=shield.ogg
buff_shield=true
View
23 mods/minicore/engine/effects.txt
@@ -1,11 +1,12 @@
-# hazard settings
-frame_size=32,32
-frame_offset=16,16
-
-# shield effect
-frame_size_sh=0,0,64,64
-frame_offset_sh=32,48
-
-# vengeance effect
-frame_size_veg=0,64,32,32
-frame_offset_veg=16,16
+# hazard settings
+frame_size=32,32
+frame_offset=16,16
+
+# status effects
+id=1
+type=shield
+gfx=shield.png
+size=0,0,64,64
+offset=32,48
+frame_total=12
+ticks_per_frame=3
View
243 mods/minicore/powers/powers.txt
@@ -1,17 +1,5 @@
# Power Definitions
-
-[power]
-id=0
-name=Shoot
-type=missile
-icon=0
-description=Basic ranged attack
-new_state=shoot
-face=true
-requires_offense_weapon=true
-base_damage=ranged
-aim_assist=32
-allow_power_mod=true
+# Do not change power with id=136 called Disenchant
[power]
id=1
@@ -35,7 +23,7 @@ id=2
name=Channel
type=missile
icon=2
-description=Channel a bolt of magic through your mental weapon for zero MP
+description=Basic magic attack
new_state=swing
requires_mental_weapon=true
face=true
@@ -50,8 +38,8 @@ radius=64
speed=24
frame_loop=0
frame_duration=2
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
starting_pos=melee
[power]
@@ -117,8 +105,8 @@ radius=64
speed=32
frame_loop=4
frame_duration=1
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=wind
trait_crits_impaired=25
post_power=126
@@ -139,8 +127,8 @@ rendered=true
no_attack=true
lifespan=18
frame_duration=2
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_loop=0
trait_elemental=light
starting_pos=source
@@ -159,7 +147,7 @@ requires_mp=1
multitarget=true
base_damage=ranged
aim_assist=32
-trait_armor_penetrating=true
+trait_armor_penetration=true
allow_power_mod=true
[power]
@@ -191,8 +179,8 @@ base_damage=ment
lifespan=12
radius=128
frame_duration=2
-frame_size=128,64
-frame_offset=64,32
+frame_size=256,128
+frame_offset=128,64
frame_loop=0
floor=true
active_frame=4
@@ -210,7 +198,6 @@ icon=11
description=Create a force field that absorbs damage
new_state=cast
requires_mp=1
-gfx=shield.png
sfx=shield.ogg
buff_shield=true
@@ -259,8 +246,8 @@ trait_elemental=ice
slow_duration=90
radius=64
frame_duration=3
-frame_size=32,32
-frame_offset=16,24
+frame_size=64,64
+frame_offset=32,48
frame_loop=20
start_frame=16
lifespan=20
@@ -270,7 +257,7 @@ delay=3
visual_random=3
rendered=true
complete_animation=true
-repeater_num=10
+count=10
[power]
id=15
@@ -289,8 +276,8 @@ rendered=true
no_attack=true
lifespan=16
frame_duration=3
-frame_size=32,32
-frame_offset=16,16
+frame_size=64,64
+frame_offset=32,32
frame_loop=0
floor=true
starting_pos=source
@@ -306,7 +293,7 @@ icon=16
description=Shoot three projectiles simultaneously
new_state=shoot
face=true
-missile_num=3
+count=3
missile_angle=15
requires_offense_weapon=true
requires_mp=1
@@ -343,15 +330,14 @@ base_damage=ment
lifespan=18
radius=128
frame_duration=2
-frame_size=128,64
-frame_offset=64,32
+frame_size=256,128
+frame_offset=128,64
frame_loop=0
floor=true
active_frame=4
trait_elemental=fire
starting_pos=target
multitarget=true
-post_effect=40
post_power=125
range=512
@@ -373,6 +359,82 @@ stun_duration=150
base_damage=none
[power]
+id=20
+name=Heroic Swing
+type=effect
+icon=1
+description=Melee attack with 10% HP steal
+new_state=swing
+face=true
+use_hazard=true
+rendered=false
+aim_assist=32
+base_damage=melee
+lifespan=1
+radius=64
+starting_pos=melee
+allow_power_mod=true
+hp_steal=10
+
+[power]
+id=21
+name=Greater Channel
+type=missile
+icon=2
+description=Magic attack with 10% MP steal
+new_state=swing
+requires_mental_weapon=true
+face=true
+directional=true
+gfx=channel.png
+use_hazard=true
+rendered=true
+aim_assist=32
+base_damage=ment
+lifespan=8
+radius=64
+speed=24
+frame_loop=0
+frame_duration=2
+frame_size=64,64
+frame_offset=32,64
+starting_pos=melee
+mp_steal=10
+
+[power]
+id=22
+name=Shoot
+type=missile
+icon=0
+description=Basic ranged attack
+new_state=shoot
+face=true
+requires_offense_weapon=true
+base_damage=ranged
+starting_pos=melee
+aim_assist=32
+allow_power_mod=true
+
+[power]
+id=23
+name=Rapid Fire
+type=missile
+icon=0
+description=Fire five low power missiles in quick succession
+new_state=shoot
+face=true
+requires_offense_weapon=true
+requires_mp=5
+base_damage=ranged
+starting_pos=melee
+aim_assist=32
+allow_power_mod=true
+count=5
+delay=2
+damage_multiplier=66
+cooldown=5000
+
+[power]
id=30
name=Ice Shard [enemy]
type=missile
@@ -392,8 +454,8 @@ radius=64
speed=30
frame_loop=12
frame_duration=3
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=ice
slow_duration=60
post_power=126
@@ -420,8 +482,8 @@ radius=64
speed=30
frame_loop=8
frame_duration=2
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=fire
post_power=125
wall_power=125
@@ -444,8 +506,8 @@ base_damage=ranged
lifespan=27
radius=64
speed=24
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_duration=5
frame_loop=32
@@ -464,8 +526,8 @@ base_damage=ment
lifespan=12
radius=128
frame_duration=2
-frame_size=128,64
-frame_offset=64,32
+frame_size=256,128
+frame_offset=128,64
frame_loop=0
floor=true
active_frame=4
@@ -496,8 +558,8 @@ base_damage=ranged
lifespan=16
radius=64
speed=48
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
wall_power=124
[power]
@@ -519,14 +581,14 @@ radius=64
speed=30
frame_loop=12
frame_duration=3
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=ice
slow_duration=60
post_power=126
wall_power=126
#missile num needs to be odd, or the player can avoid just by standing there
-missile_num=9
+count=9
missile_angle=40
[power]
@@ -599,7 +661,7 @@ lifespan=1
radius=64
starting_pos=melee
allow_power_mod=true
-trait_armor_penetrating=true
+trait_armor_penetration=true
[power]
id=40
@@ -619,15 +681,14 @@ base_damage=ment
lifespan=18
radius=128
frame_duration=2
-frame_size=128,64
-frame_offset=64,32
+frame_size=256,128
+frame_offset=128,64
frame_loop=0
floor=true
active_frame=4
trait_elemental=fire
starting_pos=source
multitarget=true
-post_effect=40
post_power=125
# paralyzing spit
@@ -650,8 +711,8 @@ radius=64
speed=24
frame_loop=0
frame_duration=2
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
starting_pos=melee
stun_duration=30
@@ -676,10 +737,10 @@ base_damage=ranged
lifespan=16
radius=64
speed=48
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
wall_power=124
-missile_num=3
+count=3
missile_angle=15
[power]
@@ -688,19 +749,21 @@ type=effect
icon=32
name=Health Potion
sfx=potion.ogg
-new_state=cast
+new_state=instant
requires_item=1
buff_restore_hp=25
+cooldown=600
[power]
id=101
type=effect
icon=33
name=Mana Potion
-new_state=cast
+new_state=instant
sfx=potion.ogg
requires_item=2
buff_restore_mp=25
+cooldown=600
[power]
id=102
@@ -708,19 +771,21 @@ type=effect
icon=34
name=Health Flask
sfx=potion.ogg
-new_state=cast
+new_state=instant
requires_item=3
buff_restore_hp=75
+cooldown=600
[power]
id=103
type=effect
icon=35
name=Mana Flask
-new_state=cast
+new_state=instant
sfx=potion.ogg
requires_item=4
buff_restore_mp=75
+cooldown=600
[power]
@@ -738,8 +803,8 @@ rendered=true
no_attack=true
lifespan=16
frame_duration=3
-frame_size=32,32
-frame_offset=16,16
+frame_size=64,64
+frame_offset=32,32
frame_loop=0
floor=true
starting_pos=source
@@ -766,13 +831,13 @@ radius=64
speed=30
frame_loop=4
frame_duration=1
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=wind
post_power=126
wall_power=126
requires_item=1021
-missile_num=5
+count=5
angle_variance=15
speed_variance=7
@@ -813,8 +878,8 @@ base_damage=ranged
lifespan=16
radius=64
speed=48
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
[power]
id=121
@@ -835,8 +900,8 @@ base_damage=ranged
lifespan=16
radius=64
speed=48
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
wall_power=124
[power]
@@ -858,8 +923,8 @@ radius=64
speed=30
frame_loop=8
frame_duration=2
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=fire
post_power=125
wall_power=125
@@ -883,8 +948,8 @@ radius=64
speed=30
frame_loop=12
frame_duration=3
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=ice
post_power=126
wall_power=126
@@ -902,8 +967,8 @@ no_attack=true
directional=true
lifespan=90
frame_duration=1
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_loop=1
starting_pos=target
@@ -918,8 +983,8 @@ rendered=true
no_attack=true
lifespan=24
frame_duration=4
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_loop=100
starting_pos=target
visual_random=2
@@ -935,8 +1000,8 @@ rendered=true
no_attack=true
lifespan=24
frame_duration=4
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_loop=100
starting_pos=target
visual_random=2
@@ -952,8 +1017,8 @@ rendered=true
no_attack=true
lifespan=24
frame_duration=4
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
frame_loop=100
starting_pos=target
visual_random=2
@@ -976,8 +1041,8 @@ radius=64
speed=30
frame_loop=12
frame_duration=3
-frame_size=32,32
-frame_offset=16,32
+frame_size=64,64
+frame_offset=32,64
trait_elemental=shadow
post_power=126
wall_power=126
@@ -998,8 +1063,8 @@ rendered=true
no_attack=true
lifespan=16
frame_duration=3
-frame_size=32,32
-frame_offset=16,16
+frame_size=64,64
+frame_offset=32,32
frame_loop=0
floor=true
starting_pos=source
@@ -1140,8 +1205,8 @@ speed=48
slow_duration=90
radius=48
frame_duration=2
-frame_size=32,64
-frame_offset=16,56
+frame_size=64,128
+frame_offset=32,112
frame_loop=0
lifespan=16
active_frame=0
@@ -1150,7 +1215,7 @@ delay=6
visual_random=4
rendered=true
complete_animation=true
-repeater_num=10
+count=10
[power]
id=160
@@ -1164,8 +1229,8 @@ lifespan=16
radius=48
frame_loop=0
frame_duration=2
-frame_size=32,64
-frame_offset=16,56
+frame_size=64,128
+frame_offset=32,112
starting_pos=source
active_frame=5
complete_animation=true
View
8 src/EnemyManager.cpp
@@ -298,11 +298,11 @@ void EnemyManager::addRenders(vector<Renderable> &r, vector<Renderable> &r_dead)
// draw corpses below objects so that floor loot is more visible
bool dead = (*it)->stats.corpse;
(dead ? r_dead : r).push_back(re);
- if ((*it)->stats.shield_hp > 0) {
- re = (*it)->stats.getEffectRender(STAT_EFFECT_SHIELD);
- re.sprite = powers->gfx[powers->powers[POWER_SHIELD].gfx_index]; // TODO: parameter
- (dead ? r_dead : r).push_back(re);
+ if ((*it)->stats.shield_hp == 0) {
+ (*it)->stats.removeEffect("shield");
}
+ re = powers->renderEffects(&(*it)->stats);
+ (dead ? r_dead : r).push_back(re);
}
}
View
13 src/GameStatePlay.cpp
@@ -633,16 +633,11 @@ void GameStatePlay::render() {
rens.push_back(pc_hero); // Avatar
// get additional hero overlays
- if (pc->stats.shield_hp > 0) {
- Renderable re = pc->stats.getEffectRender(STAT_EFFECT_SHIELD);
- re.sprite = powers->gfx[powers->powers[POWER_SHIELD].gfx_index]; // TODO: parameter
- rens.push_back(re);
- }
- if (pc->stats.vengeance_stacks > 0) {
- Renderable re = pc->stats.getEffectRender(STAT_EFFECT_VENGEANCE);
- re.sprite = powers->runes;
- rens.push_back(re);
+ if (pc->stats.shield_hp == 0) {
+ pc->stats.removeEffect("shield");
}
+ Renderable re = powers->renderEffects(&pc->stats);
+ rens.push_back(re);
enemies->addRenders(rens, rens_dead);
View
97 src/PowerManager.cpp
@@ -57,7 +57,7 @@ void PowerManager::loadAll() {
string test_path;
- // load each items.txt file. Individual item IDs can be overwritten with mods.
+ // load each config file
for (unsigned int i = 0; i < mods->mod_list.size(); i++) {
test_path = PATH_DATA + "mods/" + mods->mod_list[i] + "/powers/powers.txt";
@@ -65,6 +65,12 @@ void PowerManager::loadAll() {
if (fileExists(test_path)) {
this->loadPowers(test_path);
}
+
+ test_path = PATH_DATA + "mods/" + mods->mod_list[i] + "/engine/effects.txt";
+
+ if (fileExists(test_path)) {
+ this->loadEffects(test_path);
+ }
}
}
@@ -298,6 +304,60 @@ void PowerManager::loadPowers(const std::string& filename) {
}
/**
+ * Effects are defined in [mod]/engine/effects.txt
+ *
+ * @param filename The full path and filename to this engine.txt file
+ */
+void PowerManager::loadEffects(const std::string& filename) {
+ FileParser infile;
+ int input_id = 0;
+ bool skippingEntry = false;
+
+ if (infile.open(filename)) {
+ while (infile.next()) {
+ // id needs to be the first component of each effect. That is how we write
+ // data to the correct effect.
+ if (infile.key == "id") {
+ input_id = toInt(infile.val);
+ skippingEntry = input_id < 1;
+ if (skippingEntry)
+ fprintf(stderr, "Effect index out of bounds 1-%d, skipping\n", INT_MAX);
+ if (static_cast<int>(effects.size()) < input_id + 1)
+ effects.resize(input_id + 1);
+ continue;
+ }
+ if (skippingEntry)
+ continue;
+
+ infile.val = infile.val + ',';
+
+ if (infile.key == "type") {
+ effects[input_id].type = eatFirstString(infile.val,',');
+ } else if (infile.key == "gfx") {
+ SDL_Surface *surface = IMG_Load(mods->locate("images/powers/" + eatFirstString(infile.val,',')).c_str());
+ if(!surface)
+ fprintf(stderr, "Couldn't load effect sprites: %s\n", IMG_GetError());
+ effects[input_id].gfx = SDL_DisplayFormatAlpha(surface);
+ SDL_FreeSurface(surface);
+ } else if (infile.key == "size") {
+ effects[input_id].frame_size.x = eatFirstInt(infile.val, ',');
+ effects[input_id].frame_size.y = eatFirstInt(infile.val, ',');
+ effects[input_id].frame_size.w = eatFirstInt(infile.val, ',');
+ effects[input_id].frame_size.h = eatFirstInt(infile.val, ',');
+ } else if (infile.key == "offset") {
+ effects[input_id].frame_offset.x = eatFirstInt(infile.val, ',');
+ effects[input_id].frame_offset.y = eatFirstInt(infile.val, ',');
+ } else if (infile.key == "frame_total") {
+ effects[input_id].frame_total = eatFirstInt(infile.val, ',');
+ } else if (infile.key == "ticks_per_frame") {
+ effects[input_id].ticks_per_frame = eatFirstInt(infile.val, ',');
+ }
+ }
+ infile.close();
+ } else fprintf(stderr, "Unable to open %s!\n", filename.c_str());
+}
+
+/**
* Load the specified graphic for this power
*
* @param filename The .png file containing sprites for this power, assumed to be in images/powers/
@@ -732,6 +792,7 @@ void PowerManager::buff(int power_index, StatBlock *src_stats, Point target) {
else
CombatText::Instance()->addMessage(msg->get("+%d Shield",shield_amt), src_stats->pos, COMBAT_MESSAGE_BUFF, false);
src_stats->shield_hp = src_stats->shield_hp_total = shield_amt;
+ src_stats->addEffect("shield");
}
// teleport to the target location
@@ -1105,6 +1166,36 @@ void PowerManager::payPowerCost(int power_index, StatBlock *src_stats) {
}
}
+/**
+ * Render various status effects (buffs/debuffs)
+ *
+ * @param src_stats The StatBlock of the power activator
+ */
+Renderable PowerManager::renderEffects(StatBlock *src_stats) {
+ Renderable r;
+ r.map_pos.x = src_stats->pos.x;
+ r.map_pos.y = src_stats->pos.y;
+ r.sprite = NULL;
+
+ for (unsigned int j=0; j<src_stats->effects.size(); j++) {
+ for (unsigned int i=0; i<effects.size(); i++) {
+ if (src_stats->effects[j].type == effects[i].type) {
+ if (src_stats->effects[j].frame * effects[i].ticks_per_frame == effects[i].frame_total)
+ src_stats->effects[j].frame = 0;
+ r.src.x = (src_stats->effects[j].frame / effects[i].ticks_per_frame) * effects[i].frame_size.w;
+ r.src.y = effects[i].frame_size.y;
+ r.src.w = effects[i].frame_size.w;
+ r.src.h = effects[i].frame_size.h;
+ r.offset.x = effects[i].frame_offset.x;
+ r.offset.y = effects[i].frame_offset.y;
+ r.sprite = effects[i].gfx;
+ return r;
+ }
+ }
+ }
+ return r;
+}
+
PowerManager::~PowerManager() {
for (unsigned i=0; i<gfx.size(); i++) {
@@ -1120,5 +1211,9 @@ PowerManager::~PowerManager() {
sfx_filenames.clear();
SDL_FreeSurface(runes);
+
+ for (unsigned i=0; i<effects.size(); i++) {
+ SDL_FreeSurface(effects[i].gfx);
+ }
}
View
15 src/PowerManager.h
@@ -67,8 +67,7 @@ const int STARTING_POS_SOURCE = 0;
const int STARTING_POS_TARGET = 1;
const int STARTING_POS_MELEE = 2;
-// TODO: remove this restriction
-const int POWER_SHIELD = 11;
+// TODO: maybe move this to an effect?
const int POWER_SPARK_BLOOD = 127;
class Power {
@@ -265,16 +264,27 @@ class Power {
class PowerManager {
private:
+ struct Effect {
+ std::string type;
+ SDL_Surface *gfx;
+ SDL_Rect frame_size;
+ Point frame_offset;
+ int frame_total;
+ int ticks_per_frame;
+ };
+
MapCollision *collider;
void loadAll();
void loadPowers(const std::string& filename);
+ void loadEffects(const std::string& filename);
void loadGraphics();
int loadGFX(const std::string& filename);
int loadSFX(const std::string& filename);
std::vector<std::string> gfx_filenames;
std::vector<std::string> sfx_filenames;
+ std::vector<Effect> effects;
int calcDirection(int origin_x, int origin_y, int target_x, int target_y);
Point limitRange(int range, Point src, Point target);
@@ -305,6 +315,7 @@ class PowerManager {
bool canUsePower(unsigned id) const;
bool hasValidTarget(int power_index, StatBlock *src_stats, Point target);
bool spawn(const std::string& enemy_type, Point target);
+ Renderable renderEffects(StatBlock *src_stats);
std::vector<Power> powers;
std::queue<Hazard *> hazards; // output; read by HazardManager
View
85 src/StatBlock.cpp
@@ -109,11 +109,9 @@ StatBlock::StatBlock() {
forced_move_duration_total = 0;
shield_hp = 0;
shield_hp_total = 0;
- shield_frame = 0;
- vengeance_stacks = 0;
- vengeance_frame = 0;
cooldown_ticks = 0;
blocking = false;
+ effects = vector<Effect>();
// patrol waypoints
waypoint_pause = 0;
@@ -199,33 +197,6 @@ StatBlock::StatBlock() {
avoidance_per_defense = 5;
crit_base = 5;
crit_per_level = 1;
-
- // load static effects animation settings from engine config file
- FileParser infile;
- if (infile.open(mods->locate("engine/effects.txt"))) {
- while (infile.next()) {
- infile.val = infile.val + ',';
-
- if (infile.key == "frame_size_sh") {
- frame_size_sh.x = eatFirstInt(infile.val, ',');
- frame_size_sh.y = eatFirstInt(infile.val, ',');
- frame_size_sh.w = eatFirstInt(infile.val, ',');
- frame_size_sh.h = eatFirstInt(infile.val, ',');
- } else if (infile.key == "frame_offset_sh") {
- frame_offset_sh.x = eatFirstInt(infile.val, ',');
- frame_offset_sh.y = eatFirstInt(infile.val, ',');
- } else if (infile.key == "frame_size_veg") {
- frame_size_veg.x = eatFirstInt(infile.val, ',');
- frame_size_veg.y = eatFirstInt(infile.val, ',');
- frame_size_veg.w = eatFirstInt(infile.val, ',');
- frame_size_veg.h = eatFirstInt(infile.val, ',');
- } else if (infile.key == "frame_offset_veg") {
- frame_offset_veg.x = eatFirstInt(infile.val, ',');
- frame_offset_veg.y = eatFirstInt(infile.val, ',');
- }
- }
- infile.close();
- } else fprintf(stderr, "Unable to open engine/effects.txt!\n");
}
/**
@@ -516,11 +487,11 @@ void StatBlock::logic() {
}
// handle buff/debuff animations
- shield_frame++;
- if (shield_frame == 12) shield_frame = 0;
-
- vengeance_frame+= vengeance_stacks;
- if (vengeance_frame >= 24) vengeance_frame -= 24;
+ for (unsigned int i=0; i<effects.size(); i++) {
+ effects[i].frame++;
+ }
+ // shield_frame++;
+ // if (shield_frame == 12) shield_frame = 0;
// set movement type
// some creatures may shift between movement types
@@ -542,37 +513,27 @@ void StatBlock::clearEffects() {
slow_duration = 0;
haste_duration = 0;
forced_move_duration = 0;
- vengeance_stacks = 0;
}
-
-/**
- * Get the renderable for various effects on the player (buffs/debuffs)
- *
- * @param effect_type STAT_EFFECT_* consts defined in StatBlock.h
- */
-Renderable StatBlock::getEffectRender(int effect_type) {
- Renderable r;
- r.map_pos.x = pos.x;
- r.map_pos.y = pos.y;
-
- if (effect_type == STAT_EFFECT_SHIELD) {
- r.src.x = (shield_frame/3) * frame_size_sh.w;
- r.src.y = frame_size_sh.y;
- r.src.w = frame_size_sh.w;
- r.src.h = frame_size_sh.h;
- r.offset.x = frame_offset_sh.x;
- r.offset.y = frame_offset_sh.y;
+void StatBlock::addEffect(std::string effect) {
+ for (unsigned int i=0; i<effects.size(); i++) {
+ if (effects[i].type == effect) {
+ return; // already have this one
+ }
}
- else if (effect_type == STAT_EFFECT_VENGEANCE) {
- r.src.x = (vengeance_frame/6) * frame_size_veg.w;
- r.src.y = frame_size_veg.y;
- r.src.w = frame_size_veg.w;
- r.src.h = frame_size_veg.h;
- r.offset.x = frame_offset_veg.x;
- r.offset.y = frame_offset_veg.y;
+ Effect e;
+ e.type = effect;
+ e.frame = 0;
+ effects.push_back(e);
+}
+
+void StatBlock::removeEffect(std::string effect) {
+ for (unsigned int i=0; i<effects.size(); i++) {
+ if (effects[i].type == effect) {
+ effects.erase(effects.begin()+i);
+ return;
+ }
}
- return r;
}
StatBlock::~StatBlock() {
View
15 src/StatBlock.h
@@ -79,12 +79,18 @@ class StatBlock {
StatBlock();
~StatBlock();
+ struct Effect {
+ std::string type;
+ int frame;
+ };
+
void load(const std::string& filename);
void takeDamage(int dmg);
void recalc();
void logic();
void clearEffects();
- Renderable getEffectRender(int effect_type);
+ void addEffect(std::string effect);
+ void removeEffect(std::string effect);
bool alive;
bool corpse; // creature is dead and done animating
@@ -218,14 +224,9 @@ class StatBlock {
int shield_hp; // shield
int shield_hp_total;
- int shield_frame;
- SDL_Rect frame_size_sh;
- Point frame_offset_sh;
bool blocking;
int vengeance_stacks;
- int vengeance_frame;
- SDL_Rect frame_size_veg;
- Point frame_offset_veg;
+ std::vector<Effect> effects;
int speed;
int dspeed;

1 comment on commit 122978e

@AMDmi3

After this commit, enemy health bar no longer shows any text (e.g. monster name and HP). Healthbar itself still functions correctly.

Edit: forget it, this commit it unrelated.

Please sign in to comment.
Something went wrong with that request. Please try again.