From b7d3acab99fe4975d4598b6c9ac1ad88edfa8506 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 10 Nov 2015 20:37:02 +0300 Subject: Add support for casting status effect on ground. --- src/CMakeLists.txt | 1 + src/Makefile.am | 1 + src/defaults.cpp | 1 + src/effectmanager.cpp | 71 +++++++++++++++++++++++++++++++++++++---- src/effectmanager.h | 18 ++++++++++- src/game.cpp | 4 +++ src/gui/windows/skilldialog.cpp | 21 +++++++++++- src/gui/windows/skilldialog.h | 5 +++ src/net/eathena/beingrecv.cpp | 6 ++-- src/particle/particletimer.h | 39 ++++++++++++++++++++++ 10 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 src/particle/particletimer.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc5b60a3a..24ea0e3fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1045,6 +1045,7 @@ SET(SRCS particle/particleinfo.h particle/particlelist.cpp particle/particlelist.h + particle/particletimer.h particle/particlevector.cpp particle/particlevector.h party.cpp diff --git a/src/Makefile.am b/src/Makefile.am index dcf9009d2..9e7d0a6fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1057,6 +1057,7 @@ manaplus_SOURCES += main.cpp \ particle/particleinfo.h \ particle/particlelist.cpp \ particle/particlelist.h \ + particle/particletimer.h \ particle/particlevector.cpp \ particle/particlevector.h \ party.cpp \ diff --git a/src/defaults.cpp b/src/defaults.cpp index 91a092dbe..0c11be8ac 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -519,6 +519,7 @@ DefaultsData* getPathsDefaults() AddDEF("skillRemoveEffectId", -1); AddDEF("skillCastingSrcEffectId", -1); AddDEF("skillCastingDstEffectId", -1); + AddDEF("skillCastingGroundEffectId", -1); AddDEF("skillHitEffectId", -1); AddDEF("skillMissEffectId", -1); diff --git a/src/effectmanager.cpp b/src/effectmanager.cpp index e88dc0a74..3a76f3e6d 100644 --- a/src/effectmanager.cpp +++ b/src/effectmanager.cpp @@ -37,7 +37,8 @@ EffectManager *effectManager = nullptr; EffectManager::EffectManager() : - mEffects() + mEffects(), + mTimers() { logger->log1("Effects are now loading"); loadXmlFile(paths.getStringValue("effectsFile")); @@ -80,7 +81,8 @@ EffectManager::~EffectManager() { } -bool EffectManager::triggerDirection(const int id, Being *const being, +bool EffectManager::triggerDirection(const int id, + Being *const being, const SpriteDirection::Type &direction) { int rotation; @@ -110,7 +112,8 @@ bool EffectManager::triggerDirection(const int id, Being *const being, return trigger(id, being, rotation); } -bool EffectManager::trigger(const int id, Being *const being, +bool EffectManager::trigger(const int id, + Being *const being, const int rotation) { if (!being || !particleEngine) @@ -141,7 +144,8 @@ bool EffectManager::trigger(const int id, Being *const being, return rValue; } -Particle *EffectManager::triggerReturn(const int id, Being *const being, +Particle *EffectManager::triggerReturn(const int id, + Being *const being, const int rotation) { if (!being || !particleEngine) @@ -169,7 +173,9 @@ Particle *EffectManager::triggerReturn(const int id, Being *const being, return rValue; } -bool EffectManager::trigger(const int id, const int x, const int y, +bool EffectManager::trigger(const int id, + const int x, const int y, + const int endTime, const int rotation) { if (!particleEngine) @@ -183,7 +189,13 @@ bool EffectManager::trigger(const int id, const int x, const int y, { rValue = true; if (!effect.gfx.empty()) - particleEngine->addEffect(effect.gfx, x, y, rotation); + { + Particle *const particle = particleEngine->addEffect(effect.gfx, + x, y, + rotation); + if (particle) + mTimers.push_back(ParticleTimer(particle, endTime)); + } if (!effect.sfx.empty()) soundManager.playSfx(effect.sfx); // TODO add sprite effect to position @@ -203,3 +215,50 @@ void EffectManager::triggerDefault(int effectId, return; trigger(effectId, being); } + +void EffectManager::triggerDefault(int effectId, + const int x, + const int y, + const int endTime, + const int defaultEffectId) +{ + if (effectId == -1) + effectId = defaultEffectId; + if (effectId == -1) + return; + trigger(effectId, x, y, endTime); +} + +void EffectManager::logic() +{ + const int time = cur_time; + bool found(true); + while (found) + { + found = false; + FOR_EACH (std::list::iterator, it, mTimers) + { + const ParticleTimer &timer = *it; + if (timer.endTime < time) + { + found = true; + Particle *const particle = timer.particle; + if (particle) + particle->kill(); + mTimers.erase(it); + break; + } + } + } +} + +void EffectManager::clear() +{ + FOR_EACH (std::list::iterator, it, mTimers) + { + Particle *const particle = (*it).particle; + if (particle) + particle->kill(); + } + mTimers.clear(); +} diff --git a/src/effectmanager.h b/src/effectmanager.h index 0e81ffa44..16425908a 100644 --- a/src/effectmanager.h +++ b/src/effectmanager.h @@ -23,10 +23,13 @@ #ifndef EFFECTMANAGER_H #define EFFECTMANAGER_H +#include "particle/particletimer.h" + #include "resources/effectdescription.h" #include "resources/spritedirection.h" #include +#include #include "localconsts.h" @@ -60,15 +63,28 @@ class EffectManager final * Triggers a effect with the id, at * the specified x and y coordinate. */ - bool trigger(const int id, const int x, const int y, + bool trigger(const int id, + const int x, const int y, + const int endTime, const int rotation = 0); void triggerDefault(int effectId, Being *const being, const int defaultEffectId); + void triggerDefault(int effectId, + const int x, + const int y, + const int endTime, + const int defaultEffectId); + + void logic(); + + void clear(); + private: std::vector mEffects; + std::list mTimers; }; extern EffectManager *effectManager; diff --git a/src/game.cpp b/src/game.cpp index 9fe4c2508..776dd8621 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -439,6 +439,8 @@ Game::~Game() delete2(actorManager) if (client->getState() != STATE_CHANGE_MAP) delete2(localPlayer) + if (effectManager) + effectManager->clear(); delete2(effectManager) delete2(particleEngine) delete2(viewport) @@ -622,6 +624,8 @@ void Game::slowLogic() config.writeUpdated(); serverConfig.writeUpdated(); } + if (effectManager) + effectManager->logic(); } if (mainGraphics->getOpenGL()) diff --git a/src/gui/windows/skilldialog.cpp b/src/gui/windows/skilldialog.cpp index bf317b8cd..091c6c1d9 100644 --- a/src/gui/windows/skilldialog.cpp +++ b/src/gui/windows/skilldialog.cpp @@ -649,7 +649,8 @@ void SkillDialog::playCastingSrcEffect(const int id, Being *const being) const paths.getIntValue("skillCastingSrcEffectId")); } -void SkillDialog::playCastingDstEffect(const int id, Being *const being) const +void SkillDialog::playCastingDstEffect(const int id, + Being *const being) const { if (!effectManager) return; @@ -661,6 +662,24 @@ void SkillDialog::playCastingDstEffect(const int id, Being *const being) const paths.getIntValue("skillCastingDstEffectId")); } + +void SkillDialog::playCastingDstTileEffect(const int id, + const int x, + const int y, + const int delay) const +{ + if (!effectManager) + return; + SkillInfo *const info = getSkill(id); + if (!info) + return; + effectManager->triggerDefault(info->castingDstEffectId, + x * 32, + y * 32, + cur_time + delay / 1000, // end time in seconds + paths.getIntValue("skillCastingGroundEffectId")); +} + void SkillDialog::useSkill(const SkillInfo *const info, const AutoTarget autoTarget) { diff --git a/src/gui/windows/skilldialog.h b/src/gui/windows/skilldialog.h index 8f085ee22..1e5740f58 100644 --- a/src/gui/windows/skilldialog.h +++ b/src/gui/windows/skilldialog.h @@ -130,6 +130,11 @@ class SkillDialog final : public Window, void playCastingDstEffect(const int id, Being *const being) const; + void playCastingDstTileEffect(const int id, + const int x, + const int y, + const int delay) const; + void slowLogic(); void removeSkill(const int id); diff --git a/src/net/eathena/beingrecv.cpp b/src/net/eathena/beingrecv.cpp index a85d9b3ee..a18af6b11 100644 --- a/src/net/eathena/beingrecv.cpp +++ b/src/net/eathena/beingrecv.cpp @@ -766,7 +766,7 @@ void BeingRecv::processSkillCasting(Net::MessageIn &msg) const int dstY = msg.readInt16("dst y"); const int skillId = msg.readInt16("skill id"); msg.readInt32("property"); // can be used to trigger effect - msg.readInt32("cast time"); + const int castTime = msg.readInt32("cast time"); msg.readInt8("dispossable"); if (!effectManager) @@ -786,7 +786,9 @@ void BeingRecv::processSkillCasting(Net::MessageIn &msg) } else if (dstX != 0 || dstY != 0) { // being to position - UNIMPLIMENTEDPACKET; + skillDialog->playCastingDstTileEffect(skillId, + dstX, dstY, + castTime); } } diff --git a/src/particle/particletimer.h b/src/particle/particletimer.h new file mode 100644 index 000000000..ffcde3b8d --- /dev/null +++ b/src/particle/particletimer.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PARTICLE_PARTICLETIMER_H +#define PARTICLE_PARTICLETIMER_H + +class Particle; + +struct ParticleTimer final +{ + ParticleTimer(Particle *const particle0, + const int endTime0) : + particle(particle0), + endTime(endTime0) + { + } + + Particle *particle; + int endTime; +}; + +#endif // PARTICLE_PARTICLETIMER_H -- cgit v1.2.3-70-g09d2