Batch #18562 by ragnarok-clanker: forced by an admin (31 lower score(s), 132 changed function(s)); checked with 230 compiled unit(s), including every includer of Source/Client/Mode/CGameMode.h, Source/Contents/Actors/EffectActors.h, Source/Contents/Actors/GameActor.h, Source/Contents/Actors/GameObject.h, Source/Contents/Actors/GndRiser.h, Source/Contents/Actors/GroundScope.h, Source/Contents/Actors/Item.h, Source/Contents/Actors/MousePointer.h, Source/Contents/Actors/Npc.h, Source/Contents/Actors/Pc.h, Source/Contents/Actors/RenderObject.h, Source/Contents/Actors/Skill.h, Source/Contents/Effects/Core/DummyEffectLauncher.h, Source/Contents/Effects/Core/EffectActor.h, Source/Contents/Effects/Core/EffectMaker.h, Source/Contents/Effects/Core/MsgEffect.h, Source/Contents/Effects/Skills/ArrowEffect.h, Source/Contents/Effects/Skills/MandraAttackEffect.h, Source/Contents/SignBoard/SignBoard.h, Source/Contents/Skills/GraffiSkill.h, Source/Contents/Sound/SoundMaker.h.
4456 lines
156 KiB
C++
4456 lines
156 KiB
C++
#include "Client/Mode/ModeMessage.h"
|
|
#include "UI/Window/UIEnums.h"
|
|
#include "UI/Window/WindowId.h"
|
|
#include "Contents/Actors/GameObject.h"
|
|
#include "Contents/Actors/ActorEnums.h"
|
|
#include "Network/Packets/NoticeEnums.h"
|
|
#include "Contents/Jobs/JobId.h"
|
|
#include "Contents/Effects/Core/EffectTypes.h"
|
|
#include "Contents/Actors/GameActor.h"
|
|
#include "Client/Mode/ModeMgr.h"
|
|
#include "Client/Mode/CGameMode.h"
|
|
#include "Contents/Camera/Camera.h"
|
|
#include "Client/Replay/Replay.h"
|
|
#include "Client/Session/Session.h"
|
|
#include "Contents/Jobs/JobInheritance.h"
|
|
#include "Contents/World/World.h"
|
|
#include "Contents/Actors/RenderObject.h"
|
|
#include "Contents/Configuration/ServiceConfiguration.h"
|
|
#include "Contents/Effects/Core/EffectLists.h"
|
|
#include "Contents/Effects/Core/RagEffect.h"
|
|
#include "Render/DeviceContext/DCSurface.h"
|
|
#include "Render/Projection/RendererViewport.h"
|
|
#include "Render/Renderer.h"
|
|
#include "Render/Drawing/SpriteGeometry.h"
|
|
#include "Render/Primitives/SpriteQuad.h"
|
|
#include "Render/Primitives/TextureQuad.h"
|
|
#include "Render/Textures/SpriteAtlas.h"
|
|
#include "Render/Textures/Texture.h"
|
|
#include "Resource/Bitmap/PaletteResource.h"
|
|
#include "Resource/ResourceMgr.h"
|
|
#include "Resource/Sprites/ActionResource.h"
|
|
#include "Resource/Sprites/SpriteResource.h"
|
|
#include "Resource/World/TerrainResource.h"
|
|
#include "Render/Textures/SpritePixels.h"
|
|
#include "Utility/Math/AffineMatrix.h"
|
|
#include "Utility/Math/ScalarConversion.h"
|
|
#include "Contents/Monster/ChampionMonsterMgr.h"
|
|
#include "Contents/Actors/ActorStateFlags.h"
|
|
#include "Contents/Actors/Pc.h"
|
|
#include "Contents/CashEmotion/CashEmotionMgr.h"
|
|
#include "Contents/Tables/ForbiddenWords.h"
|
|
#include "Contents/Configuration/ServiceOptions.h"
|
|
#include "Contents/Effects/Core/Effect.h"
|
|
#include "Contents/Effects/Primitives/EffectPrim.h"
|
|
#include "Contents/Effects/Skills/EnergyOrbEffect.h"
|
|
#include "Contents/Effects/Skills/MonsterSkillEffects.h"
|
|
#include "Contents/Effects/Core/MsgEffect.h"
|
|
#include "Contents/Jobs/JobNames.h"
|
|
#include "Contents/Map/MapSkyMgr.h"
|
|
#include "Contents/Skills/SkillInfo.h"
|
|
#include "Contents/Sound/SoundMaker.h"
|
|
#include "Contents/Sound/SoundMgr.h"
|
|
#include "Network/Connection/Connection.h"
|
|
#include "Network/Packets/PacketLengths.h"
|
|
#include "UI/Chat/UIChatRoomTitle.h"
|
|
#include "UI/Chat/UINewChatWnd.h"
|
|
#include "UI/Buttons/UIButton.h"
|
|
#include "UI/Gauges/UIPcGage.h"
|
|
#include "UI/Shop/UIMerchantShopTitle.h"
|
|
#include "UI/Navigation/NavigationLink.h"
|
|
#include "UI/Text/UITextViewer.h"
|
|
#include "UI/Text/UITransBalloonText.h"
|
|
#include "UI/Buttons/UIBalloonOpenBtn.h"
|
|
#include "UI/Dialogs/UIMessageBox.h"
|
|
#include "UI/Window/UIWindow.h"
|
|
#include "UI/Window/UIWindowMgr.h"
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
#include <list>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <windows.h>
|
|
#include <timeapi.h>
|
|
|
|
namespace {
|
|
// VTABLE: vt_01828
|
|
class CGameObjectIDGenerator {
|
|
public:
|
|
virtual ~CGameObjectIDGenerator();
|
|
};
|
|
|
|
// GLOBAL: gl_25444
|
|
CGameObjectIDGenerator g_gameObjectIdGenerator;
|
|
}
|
|
|
|
// STATIC: 0x0135EF80
|
|
// GLOBAL: gl_21923
|
|
std::uint64_t CGameObject::s_nextIdentity = 0;
|
|
|
|
// GLOBAL: gl_24538
|
|
float g_cotangent = 0.16f;
|
|
|
|
// OFFSET: 0x00CA8600
|
|
// FUNCTION: fn_20989
|
|
CGameObject::CGameObject() : identity(++s_nextIdentity) {
|
|
}
|
|
|
|
// OFFSET: 0x00CA8EC0
|
|
// FUNCTION: fn_20995
|
|
CGameObject::~CGameObject() = default;
|
|
|
|
// OFFSET: 0x00CA8ED0
|
|
// FUNCTION: fn_20996
|
|
CGameObjectIDGenerator::~CGameObjectIDGenerator() {
|
|
}
|
|
|
|
// OFFSET: 0x00CAFD20
|
|
// FUNCTION: fn_21087
|
|
bool CGameObject::OnProcess() {
|
|
return true;
|
|
}
|
|
|
|
// OFFSET: 0x00CBF850
|
|
// FUNCTION: fn_21113
|
|
void CGameObject::SendMsg(CGameObject*, std::int64_t, std::int64_t, std::int64_t, std::int64_t, std::int64_t, std::int64_t, std::int64_t) {
|
|
}
|
|
|
|
// OFFSET: 0x00CB20A0
|
|
// FUNCTION: fn_21101
|
|
void CGameObject::Render(int) {
|
|
}
|
|
|
|
// OFFSET: 0x00CABF10
|
|
// FUNCTION: fn_21041
|
|
int CGameObject::GetDir(float rot) {
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
int longitude = 0;
|
|
|
|
if (gameMode) {
|
|
longitude = static_cast<int>(-gameMode->camera->camera.yaw - rot);
|
|
|
|
while (longitude < 0) {
|
|
longitude += 360;
|
|
}
|
|
|
|
while (longitude >= 360) {
|
|
longitude -= 360;
|
|
}
|
|
}
|
|
|
|
return longitude;
|
|
}
|
|
|
|
// OFFSET: 0x00CAB740
|
|
// FUNCTION: fn_21029
|
|
int CGameObject::Get8Dir2(float rot, int flag) {
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
|
|
if (!gameMode) {
|
|
return 0;
|
|
}
|
|
|
|
float relative = -gameMode->camera->camera.yaw - rot;
|
|
|
|
while (relative < 0.0f) {
|
|
relative += 360.0f;
|
|
}
|
|
|
|
while (relative >= 360.0f) {
|
|
relative -= 360.0f;
|
|
}
|
|
|
|
if (flag != 0) {
|
|
if (relative < 22.5f || relative > 337.5f) {
|
|
return 0;
|
|
}
|
|
|
|
return static_cast<int>((static_cast<double>(relative) + 22.5) / 45.0);
|
|
}
|
|
|
|
return static_cast<int>(relative / 45.0f);
|
|
}
|
|
|
|
// OFFSET: 0x00CAB7F0
|
|
// FUNCTION: fn_21030
|
|
int CGameActor::Get8Dir(float angle) {
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
|
|
if (!gameMode) {
|
|
return 0;
|
|
}
|
|
|
|
float relative = -gameMode->camera->camera.yaw - angle;
|
|
|
|
while (relative < 0.0f) {
|
|
relative += 360.0f;
|
|
}
|
|
|
|
while (relative >= 360.0f) {
|
|
relative -= 360.0f;
|
|
}
|
|
|
|
if ((IsPlayerJob(this->GetEffectiveJob(-1)) && (this->render.animation == 0 || this->render.animation == 8 || this->render.animation == 16)) ||
|
|
(this->GetEffectiveJob(-1) > 45 && this->GetEffectiveJob(-1) < 1000 && this->render.animation == 0) ||
|
|
(g_session.IsHirelingJob(this->GetEffectiveJob(-1)) &&
|
|
(this->render.animation == 0 || this->render.animation == 8 || this->render.animation == 16))) {
|
|
if (relative < 22.5f || relative > 337.5f) {
|
|
return 0;
|
|
}
|
|
|
|
return static_cast<int>((static_cast<double>(relative) + 22.5) / 45.0);
|
|
}
|
|
|
|
return static_cast<int>(relative / 45.0f);
|
|
}
|
|
|
|
// OFFSET: 0x00CAB920
|
|
// FUNCTION: fn_21031
|
|
int CGameObject::Get8Dir(float angle) {
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
|
|
if (gameMode) {
|
|
float relative = -gameMode->camera->camera.yaw - angle;
|
|
|
|
while (relative < 0.0f) {
|
|
relative += 360.0f;
|
|
}
|
|
|
|
while (relative >= 360.0f) {
|
|
relative -= 360.0f;
|
|
}
|
|
|
|
return static_cast<int>(relative / 45.0f);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// OFFSET: 0x00CB20B0
|
|
// FUNCTION: fn_21102
|
|
void CRenderObject::Render(int argument) {
|
|
if (this->render.visible != 0) {
|
|
this->DrawShadow(argument, this->render.scale);
|
|
this->DrawSprite(argument, false, 0.0f);
|
|
}
|
|
}
|
|
|
|
|
|
// OFFSET: 0x00CB20F0
|
|
// FUNCTION: fn_21103
|
|
void CRenderObject::DrawSprite(int argument, bool seasonal, float offset) {
|
|
const float* matrix = reinterpret_cast<const float*>(argument);
|
|
CSprRes* sprite = this->render.sprite;
|
|
CActRes* action = this->render.action;
|
|
|
|
if (g_session.guildLeader == 1 && seasonal == true) {
|
|
SYSTEMTIME time;
|
|
GetLocalTime(&time);
|
|
int job;
|
|
if (time.wDay % 3 == 0) {
|
|
job = 0x520;
|
|
} else if (time.wDay % 3 == 1) {
|
|
job = 0x56D;
|
|
} else {
|
|
job = 0x4F8;
|
|
}
|
|
|
|
char path[256];
|
|
std::sprintf(path, "몬스터\\%s.act", g_session.GetJobName(job, -1));
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "몬스터\\%s.spr", g_session.GetJobName(job, -1));
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
}
|
|
|
|
const ActionFrame& frame = action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
|
|
const float* origin = &this->render.position.x;
|
|
float position[3];
|
|
position[0] = origin[0] * matrix[0] + origin[1] * matrix[3] + origin[2] * matrix[6] + matrix[9];
|
|
position[1] = origin[0] * matrix[1] + origin[1] * matrix[4] + origin[2] * matrix[7] + matrix[10];
|
|
position[2] = origin[0] * matrix[2] + origin[1] * matrix[5] + origin[2] * matrix[8] + matrix[11];
|
|
|
|
float x;
|
|
float y;
|
|
float reciprocalDepth;
|
|
g_renderer->ProjectViewport(origin, matrix, &x, &y, &reciprocalDepth);
|
|
float distanceScale = g_renderer->ScaleDistance(reciprocalDepth);
|
|
|
|
float extra = offset;
|
|
if (CEffect* effect = g_effectMgr->Find(static_cast<int>(this->render.accountId), 2374)) {
|
|
extra += *reinterpret_cast<const float*>(&effect->scaleParameter);
|
|
}
|
|
if (g_championMonsterMgr->IsChampion(static_cast<int>(this->render.spriteJob))) {
|
|
extra += g_championMonsterMgr->GetValue(static_cast<int>(this->render.spriteJob));
|
|
}
|
|
if (extra != 0.0f) {
|
|
distanceScale *= extra;
|
|
}
|
|
|
|
this->render.distanceScale = distanceScale / g_heightScale;
|
|
const float scale =
|
|
g_renderer->UiScaleX() * (static_cast<float>(static_cast<int>(this->render.spriteOffsetX)) * this->render.scale) * this->render.distanceScale;
|
|
|
|
bool drawn = false;
|
|
RenderBounds bounds;
|
|
bounds.left = static_cast<float>(g_renderer->viewport.width);
|
|
bounds.top = static_cast<float>(g_renderer->viewport.height);
|
|
bounds.right = 0.0f;
|
|
bounds.bottom = 0.0f;
|
|
bounds.offset = reciprocalDepth;
|
|
this->ScaleByPulse(distanceScale);
|
|
|
|
for (int index = 0; index < frame.cellCount; ++index) {
|
|
const SpriteFrameCell& cell = frame.Cell(index);
|
|
if (cell.image == -1) {
|
|
continue;
|
|
}
|
|
|
|
const SpriteRleImage* image = sprite->images[cell.imageType][cell.image];
|
|
float bottomRhw;
|
|
float topRhw;
|
|
SpriteQuad quad;
|
|
int box[4];
|
|
std::uint32_t color;
|
|
if (!static_cast<CGameActor*>(this)->PrepareSprite(
|
|
index, index, distanceScale, cell, x, y, position, scale, &bottomRhw, &topRhw, image, &quad, box, &color, 0, 0, 0
|
|
)) {
|
|
continue;
|
|
}
|
|
|
|
drawn = true;
|
|
quad.image = image;
|
|
if (this->render.visibilityOptions[1] != 0) {
|
|
const float minX = quad.left < quad.right ? quad.left : quad.right;
|
|
const float maxX = quad.left > quad.right ? quad.left : quad.right;
|
|
if (bounds.left > minX) {
|
|
bounds.left = minX;
|
|
}
|
|
if (bounds.top > quad.top) {
|
|
bounds.top = quad.top;
|
|
}
|
|
if (maxX > bounds.right) {
|
|
bounds.right = maxX;
|
|
}
|
|
if (quad.bottom > bounds.bottom) {
|
|
bounds.bottom = quad.bottom;
|
|
}
|
|
}
|
|
|
|
const std::uint32_t* palette = sprite->palette;
|
|
if (this->render.bodyPalette != 0) {
|
|
palette = static_cast<CPaletteRes*>(ResourceMgr::Instance().Load(this->render.name.c_str()))->palette;
|
|
}
|
|
|
|
int blend = 257;
|
|
this->DrawSpriteEffects(&quad, &cell, box, scale, bottomRhw, topRhw, palette, image, &blend, color);
|
|
|
|
if (this->render.spriteJob == 0x235) {
|
|
quad.bottomRhw = bottomRhw - 0.0000003f;
|
|
quad.topRhw = topRhw - 0.0000003f;
|
|
}
|
|
|
|
if (IsScreenShakeActive()) {
|
|
quad.angle = 180.0f;
|
|
this->DrawQuad(quad, palette, blend, (x - quad.right) + (x - quad.left), (y - quad.bottom) + (y - quad.top), 0);
|
|
} else {
|
|
this->DrawQuad(quad, palette, blend, 0.0f, 0.0f, 0);
|
|
}
|
|
|
|
SpriteQuad overlay = quad;
|
|
if ((this->render.flags & 0x100) != 0) {
|
|
const short level = this->render.effectPhase;
|
|
bool draw = true;
|
|
if (level <= 5) {
|
|
overlay.color = (static_cast<short>(level * 50) << 24) + 0xFFFFFF;
|
|
} else if (level <= 8) {
|
|
overlay.color = 0xFFFFFFFF;
|
|
} else if (level <= 11) {
|
|
overlay.color = (static_cast<short>(895 - level * 80) << 24) + 0xFFFFFF;
|
|
} else {
|
|
draw = false;
|
|
}
|
|
|
|
if (draw) {
|
|
this->DrawQuad(overlay, palette, 5, 0.0f, 0.0f, 0);
|
|
}
|
|
}
|
|
|
|
if ((this->render.flags & 0x4000) != 0) {
|
|
this->DrawTintedQuad(overlay, 5, 5, 255, palette);
|
|
}
|
|
|
|
if ((this->render.flags & 0x40000) != 0) {
|
|
this->DrawTintedQuad(overlay, 255, 5, 5, palette);
|
|
}
|
|
}
|
|
|
|
if (drawn) {
|
|
this->SetRenderInfo(&bounds.left, x, y);
|
|
} else {
|
|
this->SetTlvert(x, y);
|
|
}
|
|
|
|
this->render.effectPhaseBytes[0] = 1;
|
|
}
|
|
|
|
// OFFSET: 0x00CB2830
|
|
// FUNCTION: fn_21104
|
|
void CGameActor::RenderMercenary(const float* matrix, int job) {
|
|
const float* origin = &this->render.position.x;
|
|
float position[3];
|
|
position[0] = origin[0] * matrix[0] + origin[1] * matrix[3] + origin[2] * matrix[6] + matrix[9];
|
|
position[1] = origin[0] * matrix[1] + origin[1] * matrix[4] + origin[2] * matrix[7] + matrix[10];
|
|
position[2] = origin[0] * matrix[2] + origin[1] * matrix[5] + origin[2] * matrix[8] + matrix[11];
|
|
|
|
float x;
|
|
float y;
|
|
float reciprocalDepth;
|
|
g_renderer->ProjectViewport(origin, matrix, &x, &y, &reciprocalDepth);
|
|
const float distanceScale = g_renderer->ScaleDistance(reciprocalDepth);
|
|
this->render.distanceScale = distanceScale / g_heightScale;
|
|
const float scale =
|
|
g_renderer->UiScaleX() * (static_cast<float>(static_cast<int>(this->render.spriteOffsetX)) * this->render.scale) * this->render.distanceScale;
|
|
|
|
char path[256];
|
|
char accessory[256];
|
|
const ActionFrame* bodyFrame;
|
|
const ActionFrame* headFrame;
|
|
int headOffsetX;
|
|
int headOffsetY;
|
|
int accessoryOffsetX;
|
|
int accessoryOffsetY;
|
|
|
|
for (char layer = 0; layer < 8; ++layer) {
|
|
int offsetX = 0;
|
|
int offsetY = 0;
|
|
|
|
if (layer >= 5 && job != JT_MER_ARCHER10 && job != JT_MER_LANCER10 && job != JT_MER_SWORDMAN10) {
|
|
continue;
|
|
}
|
|
|
|
CSprRes* sprite;
|
|
CActRes* action;
|
|
const ActionFrame* frame;
|
|
|
|
if (layer == 0) {
|
|
sprite = this->render.sprite;
|
|
action = this->render.action;
|
|
frame = &action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
if (this->render.previousAnimation < 8) {
|
|
frame = &action->Frame(this->render.previousAnimation, 0);
|
|
}
|
|
bodyFrame = frame;
|
|
} else if (layer == 1) {
|
|
if (job >= 0x1781 && job <= 0x178A) {
|
|
std::sprintf(path, "인간족\\머리통\\여\\%d_여.act", job % 23 + 1);
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\머리통\\여\\%d_여.spr", job % 23 + 1);
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
} else {
|
|
std::sprintf(path, "인간족\\머리통\\남\\%d_남.act", job % 23 + 1);
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\머리통\\남\\%d_남.spr", job % 23 + 1);
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
}
|
|
|
|
frame = &action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
if (this->render.previousAnimation < 8) {
|
|
frame = &action->Frame(this->render.previousAnimation, 0);
|
|
}
|
|
headFrame = frame;
|
|
|
|
if (headFrame->anchorCount != 0 && bodyFrame->anchorCount != 0 && headFrame->anchors[0].attachmentId == bodyFrame->anchors[0].attachmentId) {
|
|
headOffsetX = bodyFrame->anchors[0].x - headFrame->anchors[0].x;
|
|
headOffsetY = bodyFrame->anchors[0].y - headFrame->anchors[0].y;
|
|
}
|
|
offsetX = headOffsetX;
|
|
offsetY = headOffsetY;
|
|
} else if (layer == 2) {
|
|
if (job >= 0x1781 && job <= 0x178A) {
|
|
std::sprintf(path, "인간족\\용병\\활용병_활.act");
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\용병\\활용병_활.spr");
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
} else if (job >= 0x178B && job <= 0x1794) {
|
|
std::sprintf(path, "인간족\\용병\\창용병_창.act");
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\용병\\창용병_창.spr");
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
} else {
|
|
std::sprintf(path, "인간족\\용병\\검용병_검.act");
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\용병\\검용병_검.spr");
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
}
|
|
frame = &action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
} else if (layer == 3) {
|
|
if (job >= 0x1781 && job <= 0x178A) {
|
|
continue;
|
|
}
|
|
|
|
if (job >= 0x178B && job <= 0x1794) {
|
|
std::sprintf(path, "인간족\\용병\\창용병_창_검광.act");
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\용병\\창용병_창_검광.spr");
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
} else {
|
|
std::sprintf(path, "인간족\\용병\\검용병_검_검광.act");
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "인간족\\용병\\검용병_검_검광.spr");
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
}
|
|
frame = &action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
} else if (layer == 4) {
|
|
switch (job) {
|
|
case JT_MER_ARCHER01:
|
|
std::sprintf(accessory, "여\\여_털모자");
|
|
break;
|
|
case JT_MER_ARCHER02:
|
|
std::sprintf(accessory, "여\\여_골든헤드기어");
|
|
break;
|
|
case JT_MER_ARCHER03:
|
|
std::sprintf(accessory, "여\\여_대형금방울");
|
|
break;
|
|
case JT_MER_ARCHER04:
|
|
std::sprintf(accessory, "여\\여_엘리스모자");
|
|
break;
|
|
case JT_MER_ARCHER05:
|
|
std::sprintf(accessory, "여\\여_가부키가면");
|
|
break;
|
|
case JT_MER_ARCHER06:
|
|
std::sprintf(accessory, "여\\여_여왕의투구");
|
|
break;
|
|
case JT_MER_ARCHER07:
|
|
std::sprintf(accessory, "여\\여_지르타스가면");
|
|
break;
|
|
case JT_MER_ARCHER08:
|
|
std::sprintf(accessory, "여\\여_실버티아라");
|
|
break;
|
|
case JT_MER_ARCHER09:
|
|
std::sprintf(accessory, "여\\여_고양이모자");
|
|
break;
|
|
case JT_MER_ARCHER10:
|
|
std::sprintf(accessory, "여\\여_예쁜리본");
|
|
break;
|
|
case JT_MER_LANCER01:
|
|
std::sprintf(accessory, "남\\남_간호모");
|
|
break;
|
|
case JT_MER_LANCER02:
|
|
std::sprintf(accessory, "남\\남_검은눈가리개");
|
|
break;
|
|
case JT_MER_LANCER03:
|
|
std::sprintf(accessory, "남\\남_고블린가면4호");
|
|
break;
|
|
case JT_MER_LANCER04:
|
|
std::sprintf(accessory, "남\\남_양모자");
|
|
break;
|
|
case JT_MER_LANCER05:
|
|
std::sprintf(accessory, "남\\남_귀찮은너구리");
|
|
break;
|
|
case JT_MER_LANCER06:
|
|
std::sprintf(accessory, "남\\남_돈잃은자의마음");
|
|
break;
|
|
case JT_MER_LANCER07:
|
|
std::sprintf(accessory, "남\\남_마리오넷모자");
|
|
break;
|
|
case JT_MER_LANCER08:
|
|
std::sprintf(accessory, "남\\남_라이온마스크");
|
|
break;
|
|
case JT_MER_LANCER09:
|
|
std::sprintf(accessory, "남\\남_클로스헬멧");
|
|
break;
|
|
case JT_MER_LANCER10:
|
|
std::sprintf(accessory, "남\\남_로드카호의뿔");
|
|
break;
|
|
case JT_MER_SWORDMAN01:
|
|
std::sprintf(accessory, "남\\남_반창고");
|
|
break;
|
|
case JT_MER_SWORDMAN02:
|
|
std::sprintf(accessory, "남\\남_분노입");
|
|
break;
|
|
case JT_MER_SWORDMAN03:
|
|
std::sprintf(accessory, "남\\남_코끼리모자");
|
|
break;
|
|
case JT_MER_SWORDMAN04:
|
|
std::sprintf(accessory, "남\\남_야구모자");
|
|
break;
|
|
case JT_MER_SWORDMAN05:
|
|
std::sprintf(accessory, "남\\남_장례건");
|
|
break;
|
|
case JT_MER_SWORDMAN06:
|
|
std::sprintf(accessory, "남\\남_부용");
|
|
break;
|
|
case JT_MER_SWORDMAN07:
|
|
std::sprintf(accessory, "남\\남_타이거마스크");
|
|
break;
|
|
case JT_MER_SWORDMAN08:
|
|
std::sprintf(accessory, "남\\남_초승달투구");
|
|
break;
|
|
case JT_MER_SWORDMAN09:
|
|
std::sprintf(accessory, "남\\남_엔젤링모자");
|
|
break;
|
|
case JT_MER_SWORDMAN10:
|
|
std::sprintf(accessory, "남\\남_태양신의모자");
|
|
break;
|
|
}
|
|
} else if (layer == 5) {
|
|
switch (job) {
|
|
case JT_MER_ARCHER10:
|
|
std::sprintf(accessory, "여\\여_꽃잎");
|
|
break;
|
|
case JT_MER_LANCER10:
|
|
std::sprintf(accessory, "남\\남_토스트");
|
|
break;
|
|
}
|
|
} else if (layer == 6) {
|
|
switch (job) {
|
|
case JT_MER_ARCHER10:
|
|
std::sprintf(accessory, "여\\여_요정의귀");
|
|
break;
|
|
case JT_MER_LANCER10:
|
|
case JT_MER_SWORDMAN10:
|
|
std::sprintf(accessory, "남\\남_요정의귀");
|
|
break;
|
|
}
|
|
} else if (layer == 7) {
|
|
switch (job) {
|
|
case JT_MER_ARCHER10:
|
|
std::sprintf(accessory, "여\\여_미스틱로즈");
|
|
break;
|
|
case JT_MER_LANCER10:
|
|
std::sprintf(accessory, "남\\남_타키우스눈가리개");
|
|
break;
|
|
case JT_MER_SWORDMAN10:
|
|
std::sprintf(accessory, "남\\남_사이클롭스아이");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (layer >= 4) {
|
|
std::sprintf(path, "악세사리\\%s.act", accessory);
|
|
action = static_cast<CActRes*>(ResourceMgr::Instance().Load(path));
|
|
std::sprintf(path, "악세사리\\%s.spr", accessory);
|
|
sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load(path));
|
|
|
|
frame = &action->Frame(this->render.previousAnimation, this->render.curMotion);
|
|
if (this->render.previousAnimation < 8) {
|
|
frame = &action->Frame(this->render.previousAnimation, 0);
|
|
}
|
|
|
|
if (frame->anchorCount != 0 && headFrame->anchorCount != 0 && frame->anchors[0].attachmentId == headFrame->anchors[0].attachmentId) {
|
|
accessoryOffsetX = headFrame->anchors[0].x - frame->anchors[0].x;
|
|
accessoryOffsetY = headFrame->anchors[0].y - frame->anchors[0].y;
|
|
}
|
|
offsetX = headOffsetX + accessoryOffsetX;
|
|
offsetY = headOffsetY + accessoryOffsetY;
|
|
}
|
|
|
|
bool drawn = false;
|
|
float bounds[5];
|
|
bounds[0] = static_cast<float>(g_renderer->viewport.width);
|
|
bounds[1] = static_cast<float>(g_renderer->viewport.height);
|
|
bounds[2] = 0.0f;
|
|
bounds[3] = 0.0f;
|
|
bounds[4] = reciprocalDepth;
|
|
|
|
for (int index = 0; index < frame->cellCount; ++index) {
|
|
const SpriteFrameCell& cell = frame->Cell(index);
|
|
if (cell.image == -1) {
|
|
continue;
|
|
}
|
|
|
|
const SpriteRleImage* image = sprite->images[cell.imageType][cell.image];
|
|
float bottomRhw;
|
|
float topRhw;
|
|
SpriteQuad quad;
|
|
int box[4];
|
|
std::uint32_t color;
|
|
if (!this->PrepareSprite(index, index, distanceScale, cell, x, y, position, scale, &bottomRhw, &topRhw, image, &quad, box, &color, offsetX, offsetY, 0)) {
|
|
continue;
|
|
}
|
|
|
|
const unsigned char* argb = reinterpret_cast<const unsigned char*>(&color);
|
|
int blend = 0x101;
|
|
if (argb[3] < 0xFF) {
|
|
blend = 1;
|
|
}
|
|
drawn = true;
|
|
quad.image = image;
|
|
|
|
if (layer >= 4) {
|
|
blend = 1;
|
|
const float bias = static_cast<float>(layer - 4) * 0.00004f + 0.0001f;
|
|
quad.bottomRhw += bias;
|
|
quad.topRhw += bias;
|
|
}
|
|
|
|
if (this->render.visibilityOptions[1] != 0) {
|
|
const float minX = quad.left < quad.right ? quad.left : quad.right;
|
|
const float maxX = quad.left > quad.right ? quad.left : quad.right;
|
|
if (bounds[0] > minX) {
|
|
bounds[0] = minX;
|
|
}
|
|
if (bounds[1] > quad.top) {
|
|
bounds[1] = quad.top;
|
|
}
|
|
if (maxX > bounds[2]) {
|
|
bounds[2] = maxX;
|
|
}
|
|
if (quad.bottom > bounds[3]) {
|
|
bounds[3] = quad.bottom;
|
|
}
|
|
}
|
|
|
|
const std::uint32_t* palette = sprite->palette;
|
|
if (this->render.bodyPalette != 0) {
|
|
palette = static_cast<CPaletteRes*>(ResourceMgr::Instance().Load(this->render.name.c_str()))->palette;
|
|
}
|
|
|
|
if (layer <= 1) {
|
|
this->DrawPulseOutline(cell, box, scale, bottomRhw, topRhw, palette, image, color);
|
|
}
|
|
|
|
if (IsScreenShakeActive()) {
|
|
this->DrawFlippedQuad(quad, palette, blend, x, y, 0);
|
|
} else {
|
|
this->DrawQuad(quad, palette, blend, 0.0f, 0.0f, 0);
|
|
}
|
|
}
|
|
|
|
if (drawn) {
|
|
this->SetRenderInfo(bounds, x, y);
|
|
} else {
|
|
this->SetTlvert(x, y);
|
|
}
|
|
}
|
|
|
|
this->render.effectPhaseBytes[0] = 1;
|
|
}
|
|
|
|
// OFFSET: 0x00CB35F0
|
|
// FUNCTION: fn_21105
|
|
void CRenderObject::DrawShadow(int argument, float scale) {
|
|
if (this->render.spriteJob == 565 || this->render.visibilityOptions[0] == 0 || this->render.shadowScale == 0.0f || scale == 0.0f) {
|
|
return;
|
|
}
|
|
|
|
const float* matrix = reinterpret_cast<const float*>(argument);
|
|
const float z = this->render.position.z;
|
|
CGameMode* mode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
float position[3];
|
|
position[0] = this->render.position.x;
|
|
position[1] = mode->scene->terrain->Height(this->render.position.x, this->render.position.z);
|
|
position[2] = z;
|
|
const float depth = position[1] * matrix[5] + position[0] * matrix[2] + z * matrix[8] + matrix[11];
|
|
|
|
float screenX;
|
|
float screenY;
|
|
float reciprocalDepth;
|
|
g_renderer->ProjectViewport(position, matrix, &screenX, &screenY, &reciprocalDepth);
|
|
const float distanceScale = g_renderer->ScaleDistance(reciprocalDepth);
|
|
|
|
CSprRes* sprite = static_cast<CSprRes*>(ResourceMgr::Instance().Load("shadow.spr"));
|
|
CActRes* action = static_cast<CActRes*>(ResourceMgr::Instance().Load("shadow.act"));
|
|
const SpriteFrameCell& cell = action->Frame(0, 0).Cell(0);
|
|
if (cell.image == -1) {
|
|
return;
|
|
}
|
|
|
|
float pulse = 1.0f;
|
|
const SpriteRleImage* image = sprite->images[cell.imageType][0];
|
|
this->ScaleByPulse(pulse);
|
|
const double size = pulse * scale * this->render.shadowScale;
|
|
const double factor = distanceScale;
|
|
|
|
SpriteQuad quad;
|
|
quad.top = static_cast<float>(cell.y * factor * cell.scaleY * size + screenY);
|
|
quad.bottom = static_cast<float>(((image->doubleHeight + 1) * image->height + cell.y) * factor * cell.scaleY * size + screenY + 1.0);
|
|
float left = static_cast<float>(cell.x * factor * cell.scaleX * size + screenX);
|
|
quad.right = static_cast<float>(((image->doubleWidth + 1) * image->width + cell.x) * factor * cell.scaleX * size + screenX + 1.0);
|
|
if (quad.top >= static_cast<float>(g_renderer->viewport.height) || quad.bottom <= 0.0f || left >= static_cast<float>(g_renderer->viewport.width) ||
|
|
quad.right <= 0.0f) {
|
|
return;
|
|
}
|
|
|
|
quad.left = static_cast<float>(static_cast<int>(this->render.spriteOffsetX)) + left;
|
|
quad.right = static_cast<float>(static_cast<int>(this->render.spriteOffsetX)) + quad.right;
|
|
quad.color = static_cast<std::uint32_t>(((static_cast<std::uint32_t>(cell.color >> 24) << 8 | (cell.color & 0xFF)) << 8 | (cell.color >> 8 & 0xFF)) << 8) |
|
|
(cell.color >> 16 & 0xFF);
|
|
quad.bottomRhw = 1.0f / (depth - (quad.bottom - screenY) * g_cotangent) + 0.00001f;
|
|
quad.topRhw = 1.0f / (depth - (quad.top - screenY) * g_cotangent) + 0.00001f;
|
|
quad.angle = static_cast<float>(cell.rotation);
|
|
quad.image = image;
|
|
|
|
if (IsScreenShakeActive()) {
|
|
this->DrawFlippedQuad(quad, sprite->palette, 257, screenX, screenY, 0);
|
|
return;
|
|
}
|
|
|
|
this->DrawQuad(quad, sprite->palette, 257, 0.0f, 0.0f, 0);
|
|
}
|
|
|
|
// OFFSET: 0x00CB39A0
|
|
// FUNCTION: fn_21106
|
|
void CRenderObject::DrawQuad(const SpriteQuad& quad, const std::uint32_t* palette, int blend, float offsetX, float offsetY, int depthOffset) {
|
|
SpriteAtlasRecord record{};
|
|
const SpriteRleImage* image = quad.image;
|
|
CTexture* texture = static_cast<CTexture*>(const_cast<void*>(image->surface));
|
|
if (!texture) {
|
|
texture = g_renderer->atlas.Find(image, palette, record);
|
|
if (!texture) {
|
|
texture = g_renderer->atlas.Insert(*GetRenderSystemHolder()->system, image, palette, record, g_serviceType, g_resourceReuseDelay);
|
|
}
|
|
} else {
|
|
record.u0 = 0.0f;
|
|
record.v0 = 0.0f;
|
|
record.u1 = static_cast<float>(texture->ImageWidth()) / static_cast<float>(texture->TextureWidth());
|
|
record.v1 = static_cast<float>(texture->ImageHeight()) / static_cast<float>(texture->TextureHeight());
|
|
}
|
|
|
|
const double depthBias = depthOffset * 0.000001;
|
|
const double rhwBias = depthOffset * 0.0002;
|
|
const float bottomRhw = static_cast<float>(rhwBias + quad.bottomRhw);
|
|
const float topRhw = static_cast<float>(quad.topRhw + rhwBias);
|
|
const float bottomZ = RhwToDepth(static_cast<float>(depthBias + quad.bottomRhw));
|
|
const float topZ = RhwToDepth(static_cast<float>(quad.topRhw + depthBias));
|
|
|
|
RenderPrimitive* primitive = g_renderer->primitives.Acquire();
|
|
RenderVertex* vertices = primitive->vertices;
|
|
primitive->texture = texture;
|
|
|
|
if (quad.angle != 0.0f) {
|
|
const float cosine = ClientCosine(static_cast<int>(quad.angle));
|
|
const float sine = ClientSine(static_cast<int>(quad.angle));
|
|
const float halfWidth = (quad.right - quad.left) * 0.5f;
|
|
const float halfHeight = (quad.bottom - quad.top) * 0.5f;
|
|
const float centerX = quad.left + halfWidth + offsetX;
|
|
const float centerY = quad.top + halfHeight + offsetY;
|
|
const float minX = -halfWidth;
|
|
const float minY = -halfHeight;
|
|
|
|
vertices[0].x = minX * cosine - minY * sine + centerX + 0.5f;
|
|
vertices[0].y = minY * cosine + minX * sine + centerY + 0.5f;
|
|
vertices[1].x = halfWidth * cosine - minY * sine + centerX + 0.5f;
|
|
vertices[1].y = minY * cosine + halfWidth * sine + centerY + 0.5f;
|
|
vertices[2].x = minX * cosine - halfHeight * sine + centerX + 0.5f;
|
|
vertices[2].y = halfHeight * cosine + minX * sine + centerY + 0.5f;
|
|
vertices[3].x = halfWidth * cosine - halfHeight * sine + centerX + 0.5f;
|
|
vertices[3].y = halfHeight * cosine + halfWidth * sine + centerY + 0.5f;
|
|
} else {
|
|
vertices[0].x = quad.left + 0.5f;
|
|
vertices[0].y = quad.top + 0.5f;
|
|
vertices[1].x = quad.right + 0.5f;
|
|
vertices[1].y = quad.top + 0.5f;
|
|
vertices[2].x = quad.left + 0.5f;
|
|
vertices[2].y = quad.bottom + 0.5f;
|
|
vertices[3].x = quad.right + 0.5f;
|
|
vertices[3].y = quad.bottom + 0.5f;
|
|
}
|
|
|
|
if (*palette == 0xD77B) {
|
|
record.u1 -= 0.002f;
|
|
}
|
|
|
|
vertices[0].rhw = topRhw;
|
|
vertices[0].z = topZ;
|
|
vertices[0].u = record.u0;
|
|
vertices[0].v = record.v0;
|
|
vertices[0].diffuse = quad.color;
|
|
vertices[1].rhw = topRhw;
|
|
vertices[1].z = topZ;
|
|
vertices[1].u = record.u1;
|
|
vertices[1].v = record.v0;
|
|
vertices[1].diffuse = quad.color;
|
|
vertices[2].rhw = bottomRhw;
|
|
vertices[2].z = bottomZ;
|
|
vertices[2].u = record.u0;
|
|
vertices[2].v = record.v1;
|
|
vertices[2].diffuse = quad.color;
|
|
vertices[3].rhw = bottomRhw;
|
|
vertices[3].z = bottomZ;
|
|
vertices[3].u = record.u1;
|
|
vertices[3].v = record.v1;
|
|
vertices[3].diffuse = quad.color;
|
|
|
|
primitive->sourceBlend = 5;
|
|
primitive->destinationBlend = blend != 5 ? 6 : 2;
|
|
primitive->depthFlags = g_renderer->twoPass != 1;
|
|
g_renderer->queues.Submit(primitive, static_cast<std::uint16_t>(blend | this->render.blendFlags), g_renderer->fog.supported != 0, g_depthStart, g_depthEnd);
|
|
}
|
|
|
|
// OFFSET: 0x00CB3F40
|
|
// FUNCTION: fn_21107
|
|
void CRenderObject::DrawFlippedQuad(SpriteQuad& quad, const std::uint32_t* palette, int blend, float x, float y, int depthOffset) {
|
|
quad.angle = 180.0f;
|
|
this->DrawQuad(quad, palette, blend, (x - quad.right) + (x - quad.left), (y - quad.bottom) + (y - quad.top), depthOffset);
|
|
}
|
|
|
|
|
|
// OFFSET: 0x00CB3FA0
|
|
// FUNCTION: fn_21108
|
|
void CRenderObject::SetActionSpeed(float speed) {
|
|
speed *= this->render.action->Speed(this->render.animation);
|
|
|
|
if (g_replayAnimationScaling != 0) {
|
|
speed *= Replay::Instance().AnimationScale();
|
|
}
|
|
|
|
if (speed > 0.0f) {
|
|
this->render.speed = speed;
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00CB3FF0
|
|
// FUNCTION: fn_21109
|
|
void CRenderObject::SendValueMessage(int value, CGameObject* target) {
|
|
if (target) {
|
|
target->SendMsg(nullptr, AM_REQ_ATTACK, value, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00CB4070
|
|
// FUNCTION: fn_21110
|
|
void CGameActor::ApplySavedShapeShift() {
|
|
const int pending = this->savedShapeShift;
|
|
this->shapeShift = pending;
|
|
this->savedShapeShift = 0;
|
|
this->render.isLieOnGround = false;
|
|
this->render.visibilityOptions[1] = 1;
|
|
this->render.isMotionFreezed = false;
|
|
this->render.specialMotionLocked = 0;
|
|
|
|
int value;
|
|
switch (pending) {
|
|
case 1:
|
|
value = 0x1104;
|
|
break;
|
|
case 2:
|
|
value = 0x1105;
|
|
break;
|
|
default:
|
|
value = this->job;
|
|
break;
|
|
}
|
|
this->SetSprJob(value);
|
|
this->SetBodyPaletteName();
|
|
|
|
if (this->render.state != 3) {
|
|
this->render.state = 0;
|
|
this->SetState(0, 1);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00CB4100
|
|
// FUNCTION: fn_21111
|
|
void EffectActor::SendMsg(CGameObject* sender, std::int64_t message, std::int64_t b, std::int64_t c, std::int64_t, std::int64_t, std::int64_t, std::int64_t) {
|
|
switch (message) {
|
|
case AM_MASTER_DEAD:
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
(*it)->SendMsg(this, AM_MASTER_DEAD, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
this->state.effects.clear();
|
|
break;
|
|
|
|
case AM_MAKE_MAGIC_TARGET:
|
|
if (!this->state.second) {
|
|
this->state.second = this->LaunchEffect(static_cast<int>(b), vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (!this->state.second) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
this->state.second->SendMsg(nullptr, AM_SET_DURATION, 0, c, 0, 0, 0, 0);
|
|
break;
|
|
|
|
case AM_DELETE_MAGIC_TARGET:
|
|
if (this->state.second) {
|
|
const auto end = this->state.effects.end();
|
|
const auto it = std::find(this->state.effects.begin(), end, this->state.second);
|
|
if (it != end) {
|
|
(*it)->SendMsg(this, AM_MASTER_DEAD, 0, 0, 0, 0, 0, 0);
|
|
this->state.effects.erase(it);
|
|
}
|
|
|
|
this->state.second = nullptr;
|
|
}
|
|
break;
|
|
|
|
case AM_MAKE_BEGIN_SPELL:
|
|
if (!this->state.first) {
|
|
this->state.first = this->LaunchEffect(static_cast<int>(b), vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (!this->state.first) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (b > 0) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, b, 0, 0, 0, 0, 0);
|
|
this->state.first = this->LaunchEffect(static_cast<int>(b), vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (!this->state.first) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
this->state.first->SendMsg(nullptr, AM_SET_DURATION, 0, c, 0, 0, 0, 0);
|
|
break;
|
|
|
|
case AM_DELETE_BEGIN_SPELL:
|
|
if (this->state.first) {
|
|
const auto end = this->state.effects.end();
|
|
const auto it = std::find(this->state.effects.begin(), end, this->state.first);
|
|
if (it != end) {
|
|
(*it)->SendMsg(this, AM_MASTER_DEAD, 0, 0, 0, 0, 0, 0);
|
|
this->state.effects.erase(it);
|
|
}
|
|
|
|
this->state.first = nullptr;
|
|
}
|
|
break;
|
|
|
|
case AM_EFFECT_DEAD:
|
|
if (sender) {
|
|
CRagEffect* const effect = static_cast<CRagEffect*>(sender);
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
if (*it == effect) {
|
|
this->state.effects.erase(it);
|
|
|
|
if (this->state.first == effect) {
|
|
this->state.first = nullptr;
|
|
} else if (this->state.second == effect) {
|
|
this->state.second = nullptr;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AM_DELETE_EFFECT:
|
|
if (g_effectMgr->HasAllocator(static_cast<int>(b)) && sender) {
|
|
g_effectMgr->Retire(static_cast<CRenderObject*>(sender)->render.accountId, static_cast<int>(b));
|
|
return;
|
|
}
|
|
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
CRagEffect* const effect = *it;
|
|
if (!effect) {
|
|
this->state.effects.erase(it);
|
|
} else if (effect->state.type == b) {
|
|
effect->SendMsg(this, AM_MASTER_DEAD, 0, 0, 0, 0, 0, 0);
|
|
this->state.effects.erase(it);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AM_DELETE_TAGGED_EFFECT:
|
|
if (g_effectMgr->HasAllocator(static_cast<int>(c)) && sender) {
|
|
g_effectMgr->Retire(static_cast<CRenderObject*>(sender)->render.accountId, static_cast<int>(b), static_cast<int>(c));
|
|
return;
|
|
}
|
|
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
CRagEffect* const effect = *it;
|
|
if (!effect) {
|
|
this->state.effects.erase(it);
|
|
} else if (static_cast<int>(effect->state.tag) == b &&
|
|
effect->state.type == c) {
|
|
effect->SendMsg(this, AM_MASTER_DEAD, 0, 0, 0, 0, 0, 0);
|
|
this->state.effects.erase(it);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AM_EFFECT_LOOP_COUNT:
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
CRagEffect* const effect = *it;
|
|
if (!effect) {
|
|
this->state.effects.erase(it);
|
|
} else if (effect->state.type == b) {
|
|
effect->SendMsg(this, AM_EFFECT_LOOP_COUNT, 0, b, static_cast<int>(c), static_cast<int>(c >> 32), 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AM_IS_HAVE_EFFECT:
|
|
if (g_effectMgr->HasAllocator(static_cast<int>(b)) == true && sender) {
|
|
if (g_effectMgr->Has(static_cast<CRenderObject*>(sender)->render.accountId, static_cast<int>(b)) == true) {
|
|
*reinterpret_cast<int*>(static_cast<std::intptr_t>(b)) = -1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (auto it = this->state.effects.begin(); it != this->state.effects.end(); ++it) {
|
|
CRagEffect* const effect = *it;
|
|
if (!effect) {
|
|
this->state.effects.erase(it);
|
|
} else if (*reinterpret_cast<int*>(static_cast<std::intptr_t>(b)) == effect->state.type) {
|
|
*reinterpret_cast<int*>(static_cast<std::intptr_t>(b)) = -1;
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
// INLINED
|
|
int TransformSlot(int efst) {
|
|
switch (efst) {
|
|
case EFST_MONSTER_TRANSFORM:
|
|
return 0;
|
|
case EFST_KYOUGAKU:
|
|
return 1;
|
|
case EFST_ACTIVE_MONSTER_TRANSFORM:
|
|
return 2;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
struct PcStandEntry {
|
|
/* 0000 */ std::uint32_t aid;
|
|
/* 0004 */ int job;
|
|
/* 0008 */ int sex;
|
|
/* 000C */ int cellX;
|
|
/* 0010 */ int cellY;
|
|
/* 0014 */ int direction;
|
|
/* 0018 */ int speed;
|
|
/* 001C */ int xSize;
|
|
/* 0020 */ int ySize;
|
|
/* 0024 */ int head;
|
|
/* 0028 */ int weapon;
|
|
/* 002C */ int secondaryWeapon;
|
|
/* 0030 */ int accessory;
|
|
/* 0034 */ int state;
|
|
/* 0038 */ int bodyState;
|
|
/* 003C */ int effectState;
|
|
/* 0040 */ std::uint32_t stateFlags;
|
|
/* 0044 */ int healthState;
|
|
/* 0048 */ int shield;
|
|
/* 004C */ int accessory2;
|
|
/* 0050 */ int accessory3;
|
|
/* 0054 */ int headPalette;
|
|
/* 0058 */ int bodyPalette;
|
|
/* 005C */ int headDir;
|
|
/* 0060 */ int guildId;
|
|
/* 0064 */ int guildVersion;
|
|
/* 0068 */ int honor;
|
|
/* 006C */ int virtue;
|
|
/* 0070 */ int robe;
|
|
/* 0074 */ int pkState;
|
|
/* 0078 */ int bodyStyle;
|
|
};
|
|
|
|
struct PcMoveEntry {
|
|
/* 0000 */ std::uint32_t aid;
|
|
/* 0004 */ int job;
|
|
/* 0008 */ int sex;
|
|
/* 000C */ std::uint32_t moveStartTick;
|
|
/* 0010 */ int startX;
|
|
/* 0014 */ int startY;
|
|
/* 0018 */ int startSubX;
|
|
/* 001C */ int startSubY;
|
|
/* 0020 */ int destX;
|
|
/* 0024 */ int destY;
|
|
/* 0028 */ int speed;
|
|
/* 002C */ int head;
|
|
/* 0030 */ int weapon;
|
|
/* 0034 */ int secondaryWeapon;
|
|
/* 0038 */ int accessory;
|
|
/* 003C */ int bodyState;
|
|
/* 0040 */ int effectState;
|
|
/* 0044 */ std::uint32_t stateFlags;
|
|
/* 0048 */ int healthState;
|
|
/* 004C */ int shield;
|
|
/* 0050 */ int accessory2;
|
|
/* 0054 */ int accessory3;
|
|
/* 0058 */ int headPalette;
|
|
/* 005C */ int bodyPalette;
|
|
/* 0060 */ int headDir;
|
|
/* 0064 */ int guildId;
|
|
/* 0068 */ int guildVersion;
|
|
/* 006C */ int honor;
|
|
/* 0070 */ int virtue;
|
|
/* 0074 */ int robe;
|
|
/* 0078 */ int pkState;
|
|
/* 007C */ int bodyStyle;
|
|
};
|
|
}
|
|
|
|
// OFFSET: 0x00CB4800
|
|
// FUNCTION: fn_21112
|
|
void CGameActor::SendMsg(CGameObject* sender, std::int64_t message, std::int64_t b, std::int64_t c, std::int64_t d, std::int64_t e, std::int64_t f, std::int64_t g) {
|
|
CGameMode* mode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
bool visible = true;
|
|
if (this->render.accountId != g_session.m_aid) {
|
|
if (StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags) || StateFlag06(this->stateFlags)) {
|
|
visible = false;
|
|
}
|
|
}
|
|
|
|
switch (message) {
|
|
case 21:
|
|
break;
|
|
case AM_DELETE_PROHIBITEFFECT:
|
|
if (this->statusEffects[10] != 0) {
|
|
static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->RemoveObject(reinterpret_cast<CRenderObject*>(this->statusEffects[10]));
|
|
}
|
|
break;
|
|
case AM_MSGEFFECT_DEAD:
|
|
for (auto it = this->msgEffectList.begin(); it != this->msgEffectList.end(); ++it) {
|
|
if (*it == sender) {
|
|
const int effect = reinterpret_cast<int>(*it);
|
|
if (this->statusEffects[1] == effect) {
|
|
this->statusEffects[1] = 0;
|
|
} else if (this->statusEffects[0] == effect) {
|
|
this->statusEffects[0] = 0;
|
|
} else if (this->statusEffects[2] == effect) {
|
|
this->statusEffects[2] = 0;
|
|
} else if (this->statusEffects[3] == effect) {
|
|
this->statusEffects[3] = 0;
|
|
} else if (this->statusEffects[4] == effect) {
|
|
this->statusEffects[4] = 0;
|
|
} else if (this->statusEffects[5] == effect) {
|
|
this->statusEffects[5] = 0;
|
|
} else if (this->statusEffects[6] == effect) {
|
|
this->statusEffects[6] = 0;
|
|
} else if (this->statusEffects[8] == effect) {
|
|
this->statusEffects[8] = 0;
|
|
} else if (this->statusEffects[9] == effect) {
|
|
this->statusEffects[9] = 0;
|
|
} else if (this->statusEffects[7] == effect) {
|
|
this->statusEffects[7] = 0;
|
|
} else if (this->statusEffects[10] == effect) {
|
|
this->statusEffects[10] = 0;
|
|
} else if (this->statusEffects[11] == effect) {
|
|
this->statusEffects[11] = 0;
|
|
} else if (this->statusEffects[12] == effect) {
|
|
this->statusEffects[12] = 0;
|
|
}
|
|
this->msgEffectList.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case AM_SET_TARGET_AID:
|
|
this->hitTargetAid = static_cast<std::uint32_t>(b);
|
|
break;
|
|
case AM_MAKE_NUMBER: {
|
|
if ((g_session.GetSiegeMode() != 0 || g_session.GetBattleFieldMode() != 0) && g_session.IsAdminSubMode(7) == 0) {
|
|
break;
|
|
}
|
|
if (b == -29999) {
|
|
break;
|
|
}
|
|
int damage = static_cast<int>(b);
|
|
if (this->render.accountId == g_session.m_aid && (g_session.HasActiveSkillEffect(0x22) != 0 || g_session.HasActiveSkillEffect(0x15B) != 0)) {
|
|
damage = std::rand() % 22001 + 10000;
|
|
}
|
|
this->SpawnDamageDigits(reinterpret_cast<int>(sender), damage, static_cast<std::uint32_t>(c), static_cast<int>(d));
|
|
break;
|
|
}
|
|
case AM_MVP: {
|
|
CRagEffect* effect = this->LaunchEffect(0x44, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect != nullptr) {
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case AM_MAKE_MISS: {
|
|
if (!g_serviceOptions.Get(0x35)) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnDamageMsgEffect(&this->render.position, static_cast<int>(b), this->render.accountId);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
++this->damageNumberCount;
|
|
break;
|
|
}
|
|
case AM_MAKE_GUARD:
|
|
this->LaunchEffect(0x150, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
case AM_MAKE_LUCKY: {
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0xD, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case AM_CASH_EMOTION: {
|
|
if (mode == nullptr) {
|
|
break;
|
|
}
|
|
if (!g_cashEmotionMgr->IsChatProhibitEmotion(static_cast<int>(c))) {
|
|
CMsgEffect* effect = mode->SpawnCashEmotion(reinterpret_cast<int>(&this->render.position), static_cast<int>(b), static_cast<int>(c), this->render.accountId);
|
|
if (effect != nullptr) {
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
} else {
|
|
if (this->statusEffects[10] != 0) {
|
|
break;
|
|
}
|
|
CGameObject** slot = reinterpret_cast<CGameObject**>(&this->statusEffects[10]);
|
|
*slot = mode->SpawnCashEmotion(reinterpret_cast<int>(&this->render.position), static_cast<int>(b), static_cast<int>(c), this->render.accountId);
|
|
if (*slot != nullptr) {
|
|
this->msgEffectList.push_back(*slot);
|
|
(*slot)->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
mode->SendMsg(MM_PLAYER_EMOTION_END, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case AM_MAKE_CART: {
|
|
if (StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags) || this->statusEffects[1] != 0) {
|
|
break;
|
|
}
|
|
int effectIds[14][2] = {
|
|
{0x15, 0x1E}, {0x01, 0x19}, {0x10, 0x1A}, {0x11, 0x1B}, {0x12, 0x1C}, {0x13, 0x1D}, {0x2D, 0x2E},
|
|
{0x2F, 0x30}, {0x31, 0x32}, {0x33, 0x34}, {0x36, 0x37}, {0x38, 0x39}, {0x3A, 0x3B}, {0x41, 0x42},
|
|
};
|
|
int row = this->maxHp;
|
|
int baby = 0;
|
|
if (g_session.IsSuperNoviceClass(this->GetEffectiveJob(-1))) {
|
|
row = 0;
|
|
}
|
|
if (g_session.IsBabyJob(this->GetEffectiveJob(-1))) {
|
|
baby = 1;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(effectIds[row][baby], &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[1] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_CART:
|
|
case AM_DELETE_WOLF:
|
|
if (this->statusEffects[1] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[1])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[1] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_BIRD: {
|
|
if (this->statusEffects[0] != 0) {
|
|
break;
|
|
}
|
|
int effectId;
|
|
switch (this->GetEffectiveJob(-1)) {
|
|
case JT_HUNTER_H:
|
|
effectId = 0x17;
|
|
break;
|
|
case JT_HUNTER_B:
|
|
effectId = 0x18;
|
|
break;
|
|
case JT_GANGSI:
|
|
effectId = 0x20;
|
|
break;
|
|
case JT_DEATHKNIGHT:
|
|
effectId = 0x21;
|
|
break;
|
|
case JT_COLLECTOR:
|
|
effectId = 0x22;
|
|
break;
|
|
case JT_RANGER:
|
|
case JT_RANGER_H:
|
|
case JT_RANGER_B:
|
|
effectId = 0x35;
|
|
break;
|
|
case JT_WINDHAWK:
|
|
case JT_WOLF_WINDHAWK:
|
|
effectId = 0x45;
|
|
break;
|
|
default:
|
|
effectId = 0xE;
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(effectId, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
effect->SetAnimationSpeed(6.0f);
|
|
this->statusEffects[0] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_BIRD:
|
|
if (this->statusEffects[0] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[0])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
reinterpret_cast<CMsgEffect*>(this->statusEffects[0])->m_visible = false;
|
|
this->statusEffects[0] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_WOLF: {
|
|
if (this->statusEffects[1] != 0) {
|
|
break;
|
|
}
|
|
int effectId;
|
|
switch (this->GetEffectiveJob(-1)) {
|
|
case JT_RANGER:
|
|
case JT_RANGER_H:
|
|
case JT_WOLF_RANGER:
|
|
case JT_WOLF_RANGER_H:
|
|
effectId = 0x23;
|
|
break;
|
|
case JT_RANGER_B:
|
|
case JT_WOLF_RANGER_B:
|
|
effectId = 0x2A;
|
|
break;
|
|
case JT_WINDHAWK:
|
|
case JT_WOLF_WINDHAWK:
|
|
effectId = 0x46;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(effectId, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[1] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_MAKE_PKEFFECT: {
|
|
if (this->statusEffects[2] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(2, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[2] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_PKEFFECT:
|
|
if (this->statusEffects[2] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[2])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[2] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_ICEEFFECT: {
|
|
if (this->statusEffects[3] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(3, &this->render.position, this->render.accountId, visible);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[3] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_ICEEFFECT:
|
|
case 107:
|
|
if (this->statusEffects[3] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[3])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[3] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_CURSE_EFFECT: {
|
|
if (this->statusEffects[4] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(6, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[4] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_CURSE_EFFECT:
|
|
if (this->statusEffects[4] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[4])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[4] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_SLEEP_EFFECT: {
|
|
if (this->statusEffects[5] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(7, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[5] = reinterpret_cast<int>(effect);
|
|
this->SetState(10, 1);
|
|
break;
|
|
}
|
|
case AM_DELETE_SLEEP_EFFECT:
|
|
if (this->statusEffects[5] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[5])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[5] = 0;
|
|
this->SetState(this->render.previousState, 1);
|
|
}
|
|
break;
|
|
case AM_MAKE_STUN_EFFECT: {
|
|
if (this->statusEffects[6] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(8, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[6] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_STUN_EFFECT:
|
|
if (this->statusEffects[6] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[6])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[6] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_BURNING_EFFECT:
|
|
this->LaunchEffect(0x316, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
case AM_DELETE_BURNING_EFFECT:
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x316, 0, 0, 0, 0, 0);
|
|
break;
|
|
case AM_MAKE_SILENCE_EFFECT: {
|
|
if (this->statusEffects[7] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(9, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[7] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_SILENCE_EFFECT:
|
|
if (this->statusEffects[7] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[7])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[7] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_ANGELUS_EFFECT: {
|
|
if (this->statusEffects[8] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0xA, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[8] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_ANGELUS_EFFECT:
|
|
if (this->statusEffects[8] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[8])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[8] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_CRUCIS_EFFECT: {
|
|
if (this->statusEffects[9] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0xB, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[9] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_CRUCIS_EFFECT:
|
|
if (this->statusEffects[9] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[9])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[9] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_SMOKE_FFECT: {
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(5, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case AM_MAKE_ICEBREAKE_FFECT: {
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(4, &this->render.position, this->render.accountId, visible);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case AM_MAKE_CRITICAL_EFFECT: {
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0xC, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case 131: {
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0x16, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case AM_USEITEM_EFFECT:
|
|
this->LaunchEffect(7, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
case AM_WILL_BE_DEAD:
|
|
if (g_session.IsHomunAid(this->render.accountId)) {
|
|
if (g_windowMgr.homunInfoWnd != nullptr) {
|
|
g_windowMgr.CloseWindow(WID_HOMUNINFOWND);
|
|
}
|
|
if (g_windowMgr.homunculusSkillWnd != nullptr) {
|
|
g_windowMgr.CloseWindow(WID_SKILLLISTWND_SKILLTAB_0);
|
|
}
|
|
g_session.ClearHomunStatus();
|
|
g_session.homunAlive = 0;
|
|
}
|
|
if (g_session.IsMercenaryAid(this->render.accountId)) {
|
|
if (g_windowMgr.mercenaryInfoWnd != nullptr) {
|
|
g_windowMgr.CloseWindow(WID_MERINFOWND);
|
|
}
|
|
if (g_windowMgr.mercenarySkillWnd != nullptr) {
|
|
g_windowMgr.CloseWindow(WID_SKILLLISTWND_SKILLTAB_1);
|
|
}
|
|
g_session.ResetMercenaryStats();
|
|
g_session.mercenaryAlive = 0;
|
|
break;
|
|
}
|
|
if (this->willBeAttackedList.size() != 0 && !IsPlayerJob(this->GetEffectiveJob(-1))) {
|
|
this->willBeDead = 1;
|
|
break;
|
|
}
|
|
this->SetState(3, 1);
|
|
break;
|
|
case 134: {
|
|
if (this->statusEffects[11] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0x1F, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[11] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case 135:
|
|
if (this->statusEffects[11] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[11])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[11] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_LASSITUDE_EFFECT: {
|
|
if (this->statusEffects[12] != 0) {
|
|
break;
|
|
}
|
|
CMsgEffect* effect = mode->SpawnMsgEffect(0x43, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[12] = reinterpret_cast<int>(effect);
|
|
break;
|
|
}
|
|
case AM_DELETE_LASSITUDE_EFFECT:
|
|
if (this->statusEffects[12] != 0) {
|
|
reinterpret_cast<CGameObject*>(this->statusEffects[12])->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->statusEffects[12] = 0;
|
|
}
|
|
break;
|
|
case AM_DEAD:
|
|
if (this->render.state == 3) {
|
|
break;
|
|
}
|
|
this->SetState(3, 1);
|
|
break;
|
|
case AM_ATTACKED_SKILL:
|
|
case AM_ATTACKEDNOMOTION_SKILL: {
|
|
this->render.overrideColor = 0xFFFF0000;
|
|
const int effectId = reinterpret_cast<const ActorDamageMessage*>(static_cast<std::intptr_t>(b))->effectId;
|
|
if (effectId == 0xC6) {
|
|
this->render.overrideColor = 0xFF042BA4;
|
|
} else {
|
|
this->render.overrideColor = effectId == 0xB8 ? 0xFF505050 : this->render.overrideColor;
|
|
}
|
|
}
|
|
case AM_ATTACKED:
|
|
case AM_ATTACKEDNOMOTION:
|
|
case AM_ATTACKED_CRITICAL:
|
|
case AM_ATTACKED_LUCKY:
|
|
case AM_ATTACKED_MANYTIMES:
|
|
case AM_ATTACKED_MANYTIMES2:
|
|
case AM_ATTACKED_MANYTIMES2DASH:
|
|
case 148: {
|
|
const std::int64_t id = message;
|
|
const ActorDamageMessage* damageMessage = reinterpret_cast<const ActorDamageMessage*>(static_cast<std::intptr_t>(b));
|
|
const int hitEffect = damageMessage->hitEffect;
|
|
const int skillEffect = damageMessage->effectId;
|
|
const int monsterValue = damageMessage->monsterValue;
|
|
int damage = damageMessage->damage;
|
|
const std::uint32_t attackerAid = damageMessage->attackerAid;
|
|
const float motionSpeed = damageMessage->motionSpeed;
|
|
if (damageMessage->cellX != -1 && damageMessage->cellY != -1) {
|
|
mode->CellCenter(damageMessage->cellX, damageMessage->cellY, this->damageDestX, this->damageDestZ);
|
|
} else {
|
|
this->damageDestX = this->render.position.x;
|
|
this->damageDestZ = this->render.position.z;
|
|
}
|
|
|
|
int job = this->GetEffectiveJob(-1);
|
|
std::int64_t weapon = -1;
|
|
CGameActor* attacker;
|
|
if (g_session.m_aid == attackerAid) {
|
|
attacker = mode->scene->player;
|
|
} else {
|
|
attacker = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(attackerAid));
|
|
}
|
|
if (attacker != nullptr) {
|
|
job = attacker->GetEffectiveJob(-1);
|
|
weapon = attacker->GetWeapon();
|
|
}
|
|
|
|
if (id == 94) {
|
|
this->SendMsg(nullptr, AM_MAKE_LUCKY, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
bool negative = false;
|
|
if (damage < 0 && damage != -29999) {
|
|
damage = -damage;
|
|
negative = true;
|
|
}
|
|
|
|
if (damage == 0) {
|
|
if (attacker != nullptr) {
|
|
if ((job >= 45 && job < 1000) || g_session.IsMonsterClass(job)) {
|
|
if ((this->render.accountId == g_session.m_aid && g_session.HasActiveSkillEffect(19)) ||
|
|
(this->render.accountId == g_session.m_aid && g_session.HasActiveSkillEffect(104))) {
|
|
this->SendMsg(nullptr, AM_MAKE_GUARD, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
attacker->SendMsg(nullptr, AM_MAKE_MISS, static_cast<std::uint32_t>(-1), 0, 0, 0, 0, 0);
|
|
}
|
|
} else {
|
|
attacker->SendMsg(nullptr, AM_MAKE_MISS, 0xFFFF0000u, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
} else {
|
|
if (g_session.m_aid == attackerAid) {
|
|
this->lastDamage = damage;
|
|
} else {
|
|
this->damageNumberCount = 0;
|
|
}
|
|
|
|
this->render.started = timeGetTime();
|
|
vector3d offset{0.0f, 0.0f, 0.0f};
|
|
if (damageMessage->effectId == -2) {
|
|
this->render.isSingleColor = false;
|
|
} else {
|
|
this->render.isSingleColor = true;
|
|
const vector3d* playerPosition = &mode->scene->player->render.position;
|
|
const char* wave;
|
|
if (id == 96 || id == 97) {
|
|
wave = g_session.GetWeaponHitWaveName(-1);
|
|
} else if (IsPlayerJob(this->GetEffectiveJob(-1))) {
|
|
wave = g_session.GetHitWaveName(this->GetEffectiveJob(-1));
|
|
} else {
|
|
bool genericWeapon = true;
|
|
int view = 0;
|
|
if (attacker != nullptr) {
|
|
switch (attacker->GetEffectiveJob(-1)) {
|
|
case JT_ASSASSIN:
|
|
case JT_ASSASSIN_H:
|
|
case JT_ASSASSIN_B:
|
|
case JT_GUILLOTINE_CROSS:
|
|
case JT_GUILLOTINE_CROSS_H:
|
|
case JT_GUILLOTINE_CROSS_B:
|
|
case JT_SHADOW_CROSS:
|
|
case JT_ABYSS_CHASER:
|
|
view = static_cast<int>(weapon);
|
|
if (view > 1000) {
|
|
view = GetWeaponViewValue(view);
|
|
}
|
|
genericWeapon = false;
|
|
break;
|
|
case JT_DRUID:
|
|
case JT_DRUID_B:
|
|
case JT_KARNOS:
|
|
case JT_KARNOS_B:
|
|
case JT_ALITEA:
|
|
if (attacker->shapeShift != 0) {
|
|
view = -1;
|
|
genericWeapon = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (genericWeapon) {
|
|
std::int64_t weaponView = weapon;
|
|
if (weaponView > 1000) {
|
|
weaponView = GetWeaponViewValue(static_cast<int>(weaponView));
|
|
}
|
|
view = static_cast<int>(weaponView);
|
|
}
|
|
wave = g_session.GetWeaponHitWaveName(view);
|
|
}
|
|
g_soundMgr->PlayWave(wave, this->render.position.x - playerPosition->x, 0.0f, this->render.position.z - playerPosition->z, 250, 40, 1.0f, 0);
|
|
}
|
|
|
|
if (hitEffect == 1567) {
|
|
vector3d position = this->render.position;
|
|
const int offsetX = std::max(rand() % 10, 0);
|
|
const int offsetY = std::max(rand() % 10, 0);
|
|
const int direction = std::max(rand() % 4, 0);
|
|
if (direction == 0) {
|
|
position.x += static_cast<float>(offsetX);
|
|
position.y += static_cast<float>(offsetY);
|
|
} else if (direction == 1) {
|
|
position.x += static_cast<float>(offsetX);
|
|
position.y -= static_cast<float>(offsetY);
|
|
} else if (direction == 2) {
|
|
position.x -= static_cast<float>(offsetX);
|
|
position.y += static_cast<float>(offsetY);
|
|
} else if (direction == 3) {
|
|
position.x -= static_cast<float>(offsetX);
|
|
position.y -= static_cast<float>(offsetY);
|
|
}
|
|
CEffect* effect = g_effectMgr->Spawn(0, 1567, position, 0, -1, 0, 0);
|
|
effect->SetAngle(static_cast<float>(std::max(rand() % 360, 0)));
|
|
} else if (hitEffect == 2132) {
|
|
const vector3d& playerPosition = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player->render.position;
|
|
g_soundMgr->PlayWave("effect\\ABC_DEFT_STAB2.wav", playerPosition.x - this->render.position.x, 0.0f, playerPosition.z - this->render.position.z, 250, 40, 1.0f, 0);
|
|
} else if (g_effectMgr->Spawn(this->render.accountId, hitEffect, offset, 0, -1, 0, 0) == nullptr) {
|
|
CRagEffect* effect = this->LaunchEffect(hitEffect, offset, 0.0f);
|
|
if (effect != nullptr) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 1, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
if (skillEffect == 122) {
|
|
this->render.angle += 90.0f;
|
|
if (this->render.angle > 360.0f) {
|
|
this->render.angle -= 360.0f;
|
|
}
|
|
} else if (!CSkillActionMgr::GetInstance()->OnSkillDamage(damageMessage->skillId, reinterpret_cast<int>(attacker), this, reinterpret_cast<CGameActor*>(damageMessage->skillTarget))) {
|
|
if (g_effectMgr->Spawn(this->render.accountId, skillEffect, offset, 0, -1, 0, 0) == nullptr) {
|
|
CRagEffect* effect = this->LaunchEffect(skillEffect, offset, 0.0f);
|
|
if (effect != nullptr) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 1, 0, 0, 0, 0);
|
|
if ((skillEffect == 216 || skillEffect == 217) && attacker != nullptr) {
|
|
effect->SendMsg(nullptr, AM_SETPOS, 0, reinterpret_cast<int>(&attacker->render.position), 0, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int value = damage;
|
|
std::uint32_t color;
|
|
std::int64_t kind;
|
|
std::int64_t preMessage;
|
|
if (negative) {
|
|
kind = 0;
|
|
preMessage = 0;
|
|
color = 0x72;
|
|
} else if (id == 93) {
|
|
preMessage = 92;
|
|
kind = 16;
|
|
color = 0xFFFFFF00;
|
|
} else if ((this->GetEffectiveJob(-1) >= 45 && this->GetEffectiveJob(-1) < 1000) || g_session.IsMonsterClass(this->GetEffectiveJob(-1))) {
|
|
value = monsterValue;
|
|
if (id == 129) {
|
|
preMessage = 131;
|
|
kind = 22;
|
|
color = 0xFFFFFFFF;
|
|
} else {
|
|
color = 0xFFFFFFFF;
|
|
kind = 22;
|
|
preMessage = 0;
|
|
if (id == 132) {
|
|
} else if (id == 111) {
|
|
this->SendMsg(nullptr, AM_MAKE_NUMBER, damage, damageMessage->blueDamage != 0 ? 0xFF1E90FFu : 0xFFFFFFFFu, 21, 0, 0, 0);
|
|
kind = 22;
|
|
color = 0xFFFFFF00;
|
|
} else if (id == 148) {
|
|
this->SendMsg(nullptr, AM_MAKE_CRITICAL_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
this->SendMsg(nullptr, AM_MAKE_NUMBER, damage, 0xFFFFFF00u, 16, 0, 0, 0);
|
|
kind = 22;
|
|
color = 0xFFFFFF00;
|
|
} else {
|
|
value = damage;
|
|
color = 0xFFFFFFFF;
|
|
kind = 14;
|
|
}
|
|
}
|
|
} else {
|
|
kind = 14;
|
|
preMessage = 0;
|
|
color = 0xFFFF0000;
|
|
}
|
|
|
|
if (damageMessage->blueDamage != 0) {
|
|
color = 0xFF1E90FF;
|
|
}
|
|
if (preMessage != 0) {
|
|
this->SendMsg(nullptr, preMessage, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
this->SendMsg(nullptr, AM_MAKE_NUMBER, value, static_cast<std::uint32_t>(color), kind, 0, 0, 0);
|
|
|
|
if (!negative) {
|
|
const auto isPlayer = IsPlayerJob(this->GetEffectiveJob(-1));
|
|
if (this->render.state != 3) {
|
|
if (isPlayer) {
|
|
if (this->render.state != 2 && id != 39 && id != 97) {
|
|
this->SetState(4, 1);
|
|
if (motionSpeed > 1.0f) {
|
|
this->render.motionFinishThreshold = motionSpeed;
|
|
} else {
|
|
this->SetAnimationSpeed(motionSpeed * this->render.speed);
|
|
}
|
|
}
|
|
} else if (id != 39 && id != 97) {
|
|
if (!g_session.IsMonsterActor(this) || !(motionSpeed < -0.00001f)) {
|
|
this->SetState(4, 1);
|
|
if (motionSpeed > 1.0f) {
|
|
this->render.motionFinishThreshold = motionSpeed;
|
|
} else {
|
|
this->SetAnimationSpeed(motionSpeed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this->willBeDead != 0 && this->willBeAttackedList.size() <= 1) {
|
|
this->SendMsg(nullptr, AM_DEAD, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case 108:
|
|
this->SetState(2, 1);
|
|
this->attackMotion = static_cast<float>(this->GetAttackMotion());
|
|
this->RegisterPos();
|
|
this->render.motionStartTime = timeGetTime();
|
|
this->render.curMotion = 4;
|
|
this->SetAnimationSpeed(1.0f);
|
|
this->render.previousAnimation += this->Get8Dir(this->render.angle);
|
|
if (this->willBeDead != 0 && this->willBeAttackedList.size() <= 1) {
|
|
this->SendMsg(nullptr, AM_DEAD, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case AM_WILL_BE_ATTACKED: {
|
|
ActorDamageMessage* damage = reinterpret_cast<ActorDamageMessage*>(static_cast<std::intptr_t>(b));
|
|
if (c != 0) {
|
|
if (damage->action != 0x94) {
|
|
damage->action = 0x6F;
|
|
}
|
|
damage->monsterValue = static_cast<int>(c);
|
|
}
|
|
this->willBeAttackedList.push_back(*damage);
|
|
break;
|
|
}
|
|
case AM_WILL_BE_ATTACKED2: {
|
|
ActorDamageMessage* damage = reinterpret_cast<ActorDamageMessage*>(static_cast<std::intptr_t>(b));
|
|
if (c != 0) {
|
|
damage->monsterValue = static_cast<int>(c);
|
|
damage->action = 0x81;
|
|
}
|
|
this->willBeAttackedList.push_back(*damage);
|
|
break;
|
|
}
|
|
case AM_WILL_BE_ATTACKED2DASH: {
|
|
ActorDamageMessage* damage = reinterpret_cast<ActorDamageMessage*>(static_cast<std::intptr_t>(b));
|
|
if (c != 0) {
|
|
damage->monsterValue = static_cast<int>(c);
|
|
damage->action = 0x84;
|
|
}
|
|
this->willBeAttackedList.push_back(*damage);
|
|
break;
|
|
}
|
|
case AM_SKILL:
|
|
this->ProcessSkillMessage(sender, reinterpret_cast<const ActorSkillInfo*>(static_cast<std::intptr_t>(b)), static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case AM_GROUNDSKILL:
|
|
this->PlayGroundSkillEffect(reinterpret_cast<int>(sender), reinterpret_cast<const int*>(static_cast<std::intptr_t>(b)), static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case AM_ACTION:
|
|
this->ProcessHitMessage(sender, reinterpret_cast<const ActorHitInfo*>(static_cast<std::intptr_t>(b)), static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case AM_ATTR_STATE_CHANGE: {
|
|
const int* states = reinterpret_cast<const int*>(static_cast<std::intptr_t>(b));
|
|
this->SetStatusStates(states[0], states[1], states[2], true);
|
|
this->healthState = states[3];
|
|
break;
|
|
}
|
|
case AM_STANDENTRY: {
|
|
PcStandEntry* entry = reinterpret_cast<PcStandEntry*>(static_cast<std::intptr_t>(b));
|
|
switch (this->objectType) {
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
case 14:
|
|
this->emblemVersion = entry->pkState;
|
|
break;
|
|
}
|
|
mode->CellCenter(entry->cellX, entry->cellY, this->render.position.x, this->render.position.z);
|
|
this->render.position.y =
|
|
mode->scene->terrain->Height(this->render.position.x, this->render.position.z);
|
|
this->render.angle = static_cast<float>((entry->direction + 4) * 45);
|
|
this->xSize = entry->xSize;
|
|
this->ySize = entry->ySize;
|
|
this->movementState[5] = entry->cellX;
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = entry->cellY;
|
|
*reinterpret_cast<int*>(this->headType) = entry->head;
|
|
this->SetStatusStates(entry->bodyState, entry->stateFlags, entry->effectState, false);
|
|
this->SetState(0, 1);
|
|
this->SetGuildInfo(entry->guildId, entry->guildVersion);
|
|
break;
|
|
}
|
|
case AM_INITSTANDENTRY: {
|
|
PcStandEntry* entry = reinterpret_cast<PcStandEntry*>(static_cast<std::intptr_t>(b));
|
|
switch (this->objectType) {
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
case 14:
|
|
this->emblemVersion = entry->pkState;
|
|
break;
|
|
}
|
|
this->render.accountId = entry->aid;
|
|
entry->job = MountedJob(entry->job, entry->stateFlags);
|
|
this->SetSprAct(entry->job, entry->sex, 0);
|
|
mode->CellCenter(entry->cellX, entry->cellY, this->render.position.x, this->render.position.z);
|
|
this->render.position.y =
|
|
mode->scene->terrain->Height(this->render.position.x, this->render.position.z);
|
|
if (this->objectType == 5) {
|
|
const int job = this->job;
|
|
if ((job >= 0x5248 && job <= 0x5260) || (job >= 0x5817 && job <= 0x588C)) {
|
|
entry->direction += 4;
|
|
}
|
|
}
|
|
this->render.angle = static_cast<float>((entry->direction + 4) * 45);
|
|
this->xSize = entry->xSize;
|
|
this->ySize = entry->ySize;
|
|
this->movementState[5] = entry->cellX;
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = entry->cellY;
|
|
*reinterpret_cast<int*>(&this->destinationAndSpeed[4]) = entry->speed;
|
|
*reinterpret_cast<int*>(this->headType) = entry->head;
|
|
this->SetStatusStates(entry->bodyState, entry->stateFlags, entry->effectState, false);
|
|
if (Replay::Instance().state == 6) {
|
|
switch (entry->state) {
|
|
case PCSTATE_DEAD:
|
|
this->SetState(3, 1);
|
|
break;
|
|
case PCSTATE_SIT:
|
|
this->SetState(6, 1);
|
|
break;
|
|
default:
|
|
this->SetState(0, 1);
|
|
break;
|
|
}
|
|
} else {
|
|
this->SetState(0, 1);
|
|
}
|
|
this->healthState = entry->healthState;
|
|
if (entry->job == 0x2D2 || entry->job == 0x508) {
|
|
this->SetGuildInfo(entry->guildId, entry->guildVersion);
|
|
}
|
|
this->SetPropensityInfo(entry->honor, entry->virtue);
|
|
if (c == 1) {
|
|
this->render.color = 0x44FFFFFF;
|
|
} else if (c == 2 && !StateFlag06(entry->stateFlags)) {
|
|
this->LaunchEffect(0x158, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case AM_INITMOVEENTRY:
|
|
case AM_INITMOVEENTRY2: {
|
|
PcMoveEntry* entry = reinterpret_cast<PcMoveEntry*>(static_cast<std::intptr_t>(b));
|
|
switch (this->objectType) {
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
case 14:
|
|
this->emblemVersion = entry->pkState;
|
|
break;
|
|
}
|
|
this->render.accountId = entry->aid;
|
|
entry->job = MountedJob(entry->job, entry->stateFlags);
|
|
*reinterpret_cast<int*>(this->headType) = entry->head;
|
|
this->SetSprAct(entry->job, entry->sex, 0);
|
|
this->SetStatusStates(entry->bodyState, entry->stateFlags, entry->effectState, false);
|
|
this->healthState = entry->healthState;
|
|
this->SetGuildInfo(entry->guildId, entry->guildVersion);
|
|
this->SetPropensityInfo(entry->honor, entry->virtue);
|
|
*reinterpret_cast<int*>(&this->destinationAndSpeed[4]) = entry->speed;
|
|
this->routeStartTick = entry->moveStartTick;
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
gameMode->CellCenter(entry->startX, entry->startY, this->render.position.x, this->render.position.z);
|
|
this->render.position.x += static_cast<float>(gameMode->scene->terrain->cellSize) * 0.0625f * static_cast<float>(entry->startSubX - 8);
|
|
this->render.position.z += static_cast<float>(gameMode->scene->terrain->cellSize) * 0.0625f * static_cast<float>(entry->startSubY - 8);
|
|
this->render.position.y =
|
|
gameMode->scene->terrain->Height(this->render.position.x, this->render.position.z);
|
|
if (this->FindRoute(entry->startX, entry->startY, entry->startSubX, entry->startSubY, entry->destX, entry->destY, entry->speed)) {
|
|
this->movementState[5] = entry->destX;
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = entry->destY;
|
|
this->SetState(1, 1);
|
|
this->pathStartCell = 0;
|
|
} else {
|
|
this->SetState(0, 1);
|
|
}
|
|
break;
|
|
}
|
|
case AM_MOVEENTRY:
|
|
case AM_MOVEENTRY2: {
|
|
PcMoveEntry* entry = reinterpret_cast<PcMoveEntry*>(static_cast<std::intptr_t>(b));
|
|
switch (this->objectType) {
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
case 14:
|
|
this->emblemVersion = entry->pkState;
|
|
break;
|
|
}
|
|
*reinterpret_cast<int*>(&this->destinationAndSpeed[4]) = entry->speed;
|
|
this->routeStartTick = entry->moveStartTick;
|
|
entry->job = MountedJob(entry->job, entry->stateFlags);
|
|
*reinterpret_cast<int*>(this->headType) = entry->head;
|
|
this->SetSprAct(entry->job, entry->sex, 1);
|
|
this->SetStatusStates(entry->bodyState, entry->stateFlags, entry->effectState, false);
|
|
this->healthState = entry->healthState;
|
|
this->SetGuildInfo(entry->guildId, entry->guildVersion);
|
|
this->SetPropensityInfo(entry->honor, entry->virtue);
|
|
if (this->FindRoute(entry->startX, entry->startY, entry->startSubX, entry->startSubY, entry->destX, entry->destY, entry->speed)) {
|
|
this->movementState[5] = entry->destX;
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = entry->destY;
|
|
this->SetState(1, 1);
|
|
this->pathStartCell = 0;
|
|
}
|
|
break;
|
|
}
|
|
case AM_MOVE: {
|
|
const int* route = reinterpret_cast<const int*>(static_cast<std::intptr_t>(b));
|
|
this->routeStartTick = route[0];
|
|
if (this->FindRoute(route[1], route[2], route[3], route[4], route[5], route[6], *reinterpret_cast<const int*>(&this->destinationAndSpeed[4]))) {
|
|
this->movementState[5] = route[5];
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = route[6];
|
|
this->SetState(1, 1);
|
|
this->pathStartCell = 0;
|
|
} else {
|
|
this->SetState(0, 1);
|
|
}
|
|
break;
|
|
}
|
|
case AM_DELETE_SHOP_TITLE:
|
|
if (this->actorWindows[2] != 0) {
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->actorWindows[2]));
|
|
this->actorWindows[2] = 0;
|
|
}
|
|
break;
|
|
case AM_DELETE_CHAT_TITLE:
|
|
if (this->actorWindows[1] != 0) {
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->actorWindows[1]));
|
|
this->actorWindows[1] = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_SHOP_TITLE:
|
|
if (this->actorWindows[2] == 0) {
|
|
UIMerchantShopTitle* title = new UIMerchantShopTitle(0);
|
|
this->actorWindows[2] = reinterpret_cast<int>(title);
|
|
title->SetSize(140, 34);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->actorWindows[2]));
|
|
}
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[2])->SendMsg(nullptr, UM_SETINFO, b, static_cast<std::int16_t>(this->render.fontSequenceState), 0, 0);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[2])->SendMsg(nullptr, UM_SETNAID, this->render.accountId, 0, 0, 0);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[2])->Move(this->render.screenX - 70, this->render.screenY - ScaleByScreenHeight(110));
|
|
if (!g_serviceOptions.Get(0xFA)) {
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[2])->Show(0);
|
|
}
|
|
break;
|
|
case AM_MAKE_CHAT_TITLE:
|
|
if (this->actorWindows[1] == 0) {
|
|
UIChatRoomTitle* title = new UIChatRoomTitle();
|
|
this->actorWindows[1] = reinterpret_cast<int>(title);
|
|
title->SetSize(140, 34);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->actorWindows[1]));
|
|
}
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[1])->SendMsg(nullptr, UM_SETINFO, b, static_cast<std::int16_t>(this->render.fontSequenceState), 0, 0);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[1])->Move(this->render.screenX - 70, this->render.screenY - ScaleByScreenHeight(110));
|
|
break;
|
|
case AM_MAKE_SKILL_RECHARGEGAGE:
|
|
if (this->actorWindows[3] == 0) {
|
|
// GLOBAL: gl_25466
|
|
static float s_gaugeOffsetY = static_cast<float>(g_renderer->viewport.height * 81 / 480);
|
|
UIRechargeGage* gauge = new UIRechargeGage();
|
|
this->actorWindows[3] = reinterpret_cast<int>(gauge);
|
|
gauge->SetSize(60, 6);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[3])->Move(
|
|
this->render.screenX - 30,
|
|
static_cast<int>(static_cast<float>(this->render.screenY) - s_gaugeOffsetY * this->render.distanceScale)
|
|
);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->actorWindows[3]));
|
|
}
|
|
this->skillRechargeEndTick = timeGetTime() + static_cast<std::uint32_t>(b);
|
|
this->skillRechargeStartTick = timeGetTime();
|
|
break;
|
|
case AM_DELETE_SKILL_RECHARGEGAGE:
|
|
if (this->actorWindows[3] != 0) {
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->actorWindows[3]));
|
|
this->actorWindows[3] = 0;
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
if (g_session.playerStatusFlags[0x0A] == true) {
|
|
std::int16_t packetType = 0x2F1;
|
|
GetRagConnection().Send(reinterpret_cast<const PacketLengths&>(GetRagConnection()).FixedLength(packetType), &packetType);
|
|
}
|
|
g_session.playerStatusFlags[0x0A] = false;
|
|
}
|
|
}
|
|
break;
|
|
case AM_CHAT: {
|
|
std::string text(reinterpret_cast<const char*>(static_cast<std::intptr_t>(b)));
|
|
if (g_windowMgr.chatWnd != nullptr) {
|
|
text = static_cast<UINewChatWnd*>(g_windowMgr.chatWnd)->ConvertChat(std::string(reinterpret_cast<const char*>(static_cast<std::intptr_t>(b))));
|
|
}
|
|
std::string linked;
|
|
DisplayNavigationLink(linked, text);
|
|
text = std::move(linked);
|
|
const char* message = reinterpret_cast<const char*>(static_cast<std::intptr_t>(b));
|
|
if (text.size() != 0) {
|
|
message = text.c_str();
|
|
}
|
|
if (std::strlen(message) != 0) {
|
|
this->chatTick = timeGetTime();
|
|
if (this->actorWindows[0] == 0) {
|
|
UITransBalloonText* created = new UITransBalloonText();
|
|
this->actorWindows[0] = reinterpret_cast<int>(created);
|
|
created->SetSize(8, 8);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->actorWindows[0]));
|
|
}
|
|
if (this->actorWindows[0] != 0) {
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
reinterpret_cast<UITransBalloonText*>(this->actorWindows[0])->m_fontMode = static_cast<std::int8_t>(g_session.chatFont[0]);
|
|
} else {
|
|
reinterpret_cast<UITransBalloonText*>(this->actorWindows[0])->m_fontMode = static_cast<std::uint16_t>(this->render.fontSequenceState);
|
|
}
|
|
reinterpret_cast<UITransBalloonText*>(this->actorWindows[0])->SetText(message, 35);
|
|
if (c != 0) {
|
|
reinterpret_cast<UITransBalloonText*>(this->actorWindows[0])->m_textColor = static_cast<std::uint32_t>(c);
|
|
reinterpret_cast<UITransBalloonText*>(this->actorWindows[0])->m_outlineColor = 0;
|
|
}
|
|
UIWindow* balloon = reinterpret_cast<UIWindow*>(this->actorWindows[0]);
|
|
const int width = balloon->geometry.width;
|
|
this->chatWidth = width;
|
|
this->chatHeight = balloon->geometry.height;
|
|
balloon->Move(this->render.screenX - width / 2, this->render.screenY - ScaleByScreenHeight(110));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AM_STOPMOVE: {
|
|
this->routeStartTick = g_session.GetServerTime();
|
|
int column;
|
|
int row;
|
|
int subColumn;
|
|
int subRow;
|
|
mode->WorldSubcell(this->render.position.x, this->render.position.z, column, row, subColumn, subRow);
|
|
bool found;
|
|
if (static_cast<int>(d) == 0) {
|
|
found = this->FindRoute(column, row, subColumn, subRow, static_cast<int>(b), static_cast<int>(c), this->isAsuraAttack != 0 ? 55 : 2);
|
|
} else {
|
|
found = this->FindRoute(column, row, subColumn, subRow, static_cast<int>(b), static_cast<int>(c), static_cast<int>(d));
|
|
}
|
|
bool lying = false;
|
|
if (e == 0) {
|
|
lying = true;
|
|
}
|
|
this->movementState[5] = static_cast<int>(b);
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = static_cast<int>(c);
|
|
if (found) {
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
gameMode->CellCenter(static_cast<int>(b), static_cast<int>(c), this->render.position.x, this->render.position.z);
|
|
this->render.position.y =
|
|
gameMode->scene->terrain->Height(this->render.position.x, this->render.position.z);
|
|
this->UnRegisterPos();
|
|
if (lying == true) {
|
|
this->damageDestX = this->render.position.x;
|
|
this->damageDestZ = this->render.position.z;
|
|
}
|
|
this->SetState(1, lying);
|
|
this->pathStartCell = 0;
|
|
if (static_cast<int>(d) == 0) {
|
|
this->isNeverAnimation = 1;
|
|
} else {
|
|
this->isNeverAnimation = 0;
|
|
this->render.isMotionFreezed = true;
|
|
}
|
|
} else {
|
|
if (g_session.moveHomunEnemy != 0) {
|
|
g_session.homunEnemyX = 0;
|
|
g_session.homunEnemyY = 0;
|
|
g_session.moveHomunEnemy = 0;
|
|
}
|
|
if (g_session.moveMercenaryEnemy != 0) {
|
|
g_session.mercenaryEnemyX = 0;
|
|
g_session.mercenaryEnemyY = 0;
|
|
g_session.moveMercenaryEnemy = 0;
|
|
}
|
|
this->SetState(0, lying);
|
|
}
|
|
break;
|
|
}
|
|
case AM_CORRECT_POS:
|
|
this->movementState[5] = static_cast<int>(b);
|
|
*reinterpret_cast<int*>(this->destinationAndSpeed) = static_cast<int>(c);
|
|
mode->CellCenter(static_cast<int>(b), static_cast<int>(c), this->render.position.x, this->render.position.z);
|
|
break;
|
|
case AM_RESURRECTION:
|
|
this->render.state = 0;
|
|
this->render.isLieOnGround = false;
|
|
this->render.visibilityOptions[1] = 1;
|
|
static_cast<CGameMode*>(g_modeMgr.GetGameMode())->waitingUseItemAck = 0;
|
|
this->SetState(0, 1);
|
|
break;
|
|
case AM_OUTOFSIGHT:
|
|
this->render.accountId = 0xFFFFFFFF;
|
|
this->levelAuraType = 0;
|
|
this->render.visibilityOptions[0] = 0;
|
|
this->vanishTime = static_cast<int>(timeGetTime() + 510);
|
|
if (this->vanishTime == 0) {
|
|
this->vanishTime = 1;
|
|
}
|
|
break;
|
|
case AM_MAKE_LEVEL99_EFFECT: {
|
|
this->hasLevelAura = 1;
|
|
const unsigned char showFirst = g_serviceOptions.Get(0x6A);
|
|
if (*reinterpret_cast<int*>(g_session.maxBaseLevel) == static_cast<signed char>(this->levelAuraType)) {
|
|
break;
|
|
}
|
|
if (StateFlag06(this->stateFlags) || StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags)) {
|
|
break;
|
|
}
|
|
if (g_session.IsMonsterClass(this->GetEffectiveJob(-1))) {
|
|
break;
|
|
}
|
|
if (this->GetEffectiveJob(-1) >= 0x52C && this->GetEffectiveJob(-1) <= 0x553) {
|
|
break;
|
|
}
|
|
if (this->GetEffectiveJob(-1) >= 0x792 && this->GetEffectiveJob(-1) <= 0x7A3) {
|
|
break;
|
|
}
|
|
if (this->GetEffectiveJob(-1) == JT_G_TREASURE_BOX) {
|
|
break;
|
|
}
|
|
this->levelAuraType = static_cast<unsigned char>(*reinterpret_cast<int*>(g_session.maxBaseLevel));
|
|
int first = 200;
|
|
int second = 0x3D0;
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x30]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x30]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x34]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x34]);
|
|
}
|
|
if (g_session.IsBabyJob(this->GetEffectiveJob(-1))) {
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x38]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x38]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x3C]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x3C]);
|
|
}
|
|
} else if (this->GetEffectiveJob(-1) > 0xFA0 || g_session.IsSuperNoviceJob(this->GetEffectiveJob(-1))) {
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x40]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x40]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x44]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x44]);
|
|
}
|
|
} else if (g_session.IsMercenaryJob(this->GetEffectiveJob(-1))) {
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x48]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x48]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x4C]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x4C]);
|
|
}
|
|
} else if (this->GetEffectiveJob(-1) >= 0x666) {
|
|
break;
|
|
}
|
|
const vector3d offset{0.0f, 0.0f, 0.0f};
|
|
if (showFirst != 0) {
|
|
if (g_effectMgr->Spawn(this->render.accountId, first, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(first, offset, 0.0f);
|
|
}
|
|
}
|
|
if (g_effectMgr->Spawn(this->render.accountId, second, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(second, offset, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case AM_MAKE_LEVEL160_EFFECT:
|
|
case 147: {
|
|
this->hasLevelAura = 1;
|
|
const unsigned char showFirst = g_serviceOptions.Get(0x6A);
|
|
if (*reinterpret_cast<int*>(g_session.maxBaseLevel) == static_cast<signed char>(this->levelAuraType)) {
|
|
break;
|
|
}
|
|
if (StateFlag06(this->stateFlags) || StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags)) {
|
|
break;
|
|
}
|
|
this->levelAuraType = static_cast<unsigned char>(*reinterpret_cast<int*>(g_session.maxBaseLevel));
|
|
int first = 0x3FE;
|
|
int second;
|
|
if (g_session.IsMercenaryJob(this->GetEffectiveJob(-1))) {
|
|
first = 0x3D2;
|
|
second = 0x3D3;
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x64]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x64]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x68]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x68]);
|
|
}
|
|
} else if (message == 0x93) {
|
|
first = 0x3D2;
|
|
second = 0x3D3;
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x54]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x54]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x58]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x58]);
|
|
}
|
|
} else {
|
|
second = 0x3FF;
|
|
if (message == 0x92) {
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x5C]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x5C]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x60]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x60]);
|
|
}
|
|
}
|
|
}
|
|
const vector3d offset{0.0f, 0.0f, 0.0f};
|
|
if (showFirst != 0) {
|
|
if (g_effectMgr->Spawn(this->render.accountId, first, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(first, offset, 0.0f);
|
|
}
|
|
}
|
|
if (g_effectMgr->Spawn(this->render.accountId, second, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(second, offset, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case 150: {
|
|
this->hasLevelAura = 1;
|
|
const unsigned char showFirst = g_serviceOptions.Get(0x6A);
|
|
if (*reinterpret_cast<int*>(g_session.maxBaseLevel) == static_cast<signed char>(this->levelAuraType)) {
|
|
break;
|
|
}
|
|
if (StateFlag06(this->stateFlags) || StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags)) {
|
|
break;
|
|
}
|
|
this->levelAuraType = static_cast<unsigned char>(*reinterpret_cast<int*>(g_session.maxBaseLevel));
|
|
int first = 0x4CA;
|
|
int second = 0x4CB;
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x6C]) > 0) {
|
|
first = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x6C]);
|
|
}
|
|
if (*reinterpret_cast<int*>(&g_session.jobLevelLimits[0x70]) > 0) {
|
|
second = *reinterpret_cast<int*>(&g_session.jobLevelLimits[0x70]);
|
|
}
|
|
const vector3d offset{0.0f, 0.0f, 0.0f};
|
|
if (showFirst != 0) {
|
|
if (g_effectMgr->Spawn(this->render.accountId, first, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(first, offset, 0.0f);
|
|
}
|
|
}
|
|
if (g_effectMgr->Spawn(this->render.accountId, second, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(second, offset, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case AM_MAKE_LEVEL4TH_EFFECT: {
|
|
this->hasLevelAura = 1;
|
|
const unsigned char showFirst = g_serviceOptions.Get(0x6A);
|
|
if (*reinterpret_cast<int*>(g_session.maxBaseLevel) == static_cast<signed char>(this->levelAuraType)) {
|
|
break;
|
|
}
|
|
if (StateFlag06(this->stateFlags) == true || StateFlag01(this->stateFlags) == true || StateFlag02(this->stateFlags) == true) {
|
|
break;
|
|
}
|
|
this->levelAuraType = static_cast<unsigned char>(*reinterpret_cast<int*>(g_session.maxBaseLevel));
|
|
const int first = g_session.m_maxLevelEffect4th;
|
|
const int second = g_session.m_maxLevelEffect4thSub;
|
|
const vector3d offset{0.0f, 0.0f, 0.0f};
|
|
if (showFirst != 0) {
|
|
if (g_effectMgr->Spawn(this->render.accountId, first, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(first, offset, 0.0f);
|
|
}
|
|
}
|
|
if (g_effectMgr->Spawn(this->render.accountId, second, this->render.position, 0, -1, 0, 0) == nullptr) {
|
|
this->LaunchEffect(second, offset, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case AM_STATUS_CHANGE: {
|
|
const bool on = c != 0;
|
|
switch (b) {
|
|
case EFST_PROVOKE:
|
|
case EFST_ENDURE:
|
|
case EFST_CONCENTRATION:
|
|
case EFST_HIDING:
|
|
case EFST_CLOAKING:
|
|
case EFST_ENCHANTPOISON:
|
|
case EFST_POISONREACT:
|
|
case EFST_QUAGMIRE:
|
|
case EFST_ANGELUS:
|
|
case EFST_BLESSING:
|
|
case EFST_CRUCIS:
|
|
case EFST_INC_AGI:
|
|
case EFST_DEC_AGI:
|
|
case EFST_SLOWPOISON:
|
|
case EFST_IMPOSITIO:
|
|
case EFST_SUFFRAGIUM:
|
|
case EFST_ASPERSIO:
|
|
case EFST_BENEDICTIO:
|
|
case EFST_KYRIE:
|
|
case EFST_MAGNIFICAT:
|
|
case EFST_GLORIA:
|
|
case EFST_LEXAETERNA:
|
|
case EFST_ADRENALINE:
|
|
case EFST_WEAPONPERFECT:
|
|
case EFST_MAXIMIZE:
|
|
case EFST_RIDING:
|
|
case EFST_FALCON:
|
|
case EFST_SHOUT:
|
|
case EFST_BROKENARMOR:
|
|
case EFST_BROKENWEAPON:
|
|
case EFST_WEAPONPROPERTY:
|
|
case EFST_ADRENALINE2:
|
|
case EFST_PLUSATTACKPOWER:
|
|
case EFST_PLUSMAGICPOWER:
|
|
case EFST_CRYSTAL:
|
|
case EFST_ATKER_ASPD:
|
|
case EFST_ATKER_MOVESPEED:
|
|
case EFST_ANGEL_PROTECT:
|
|
case EFST_ELECTRICSHOCKER:
|
|
case EFST_WUGRIDER:
|
|
case EFST_ADORAMUS:
|
|
case EFST_ACARAJE:
|
|
case EFST_WATER_SCREEN:
|
|
break;
|
|
case EFST_TWOHANDQUICKEN:
|
|
case EFST_ONEHANDQUICKEN: {
|
|
while (this->HasId(0xA6)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA6, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0x82, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_SPEARQUICKEN: {
|
|
while (this->HasId(0xA6)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA6, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0xFA, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_NJ_BUNSINJYUTSU:
|
|
while (this->HasId(0x269)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x269, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x269, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DEVIL1: {
|
|
if (this->render.accountId != g_session.m_aid) {
|
|
break;
|
|
}
|
|
if (static_cast<int>(d) >= 2 && static_cast<int>(d) <= 11) {
|
|
const int effectId = static_cast<int>(d) + 0x1D9;
|
|
if (!this->HasId(effectId)) {
|
|
this->LaunchEffect(0x1E7, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
g_soundMgr->PlayWave("effect\\_blind.wav", 0.0f, -100.0f, 0.0f, 250, 40, 1.0f, 0);
|
|
}
|
|
for (int id = 0x1DB; id < 0x1E5; ++id) {
|
|
if (this->HasId(id) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, id, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
this->LaunchEffect(effectId, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA4, 0, 0, 0, 0, 0);
|
|
CPlayer* player = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player;
|
|
if (player) {
|
|
player->skillEffect = this->LaunchEffect(0xA4, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_PROPERTYUNDEAD:
|
|
if (!on) {
|
|
if (this->HasId(0x28F)) {
|
|
vector3d position{0.0f, 0.0f, 0.0f};
|
|
do {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x28F, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x290, position, 0.0f);
|
|
} while (this->HasId(0x28F));
|
|
}
|
|
} else if (!this->HasId(0x28F)) {
|
|
this->LaunchEffect(0x28F, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SKE:
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
if (on) {
|
|
g_weatherEffect.StartDarken();
|
|
} else {
|
|
g_weatherEffect.StopDarken();
|
|
}
|
|
}
|
|
break;
|
|
case EFST_SMA_READY:
|
|
if (on) {
|
|
this->LaunchEffect(0x222, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_EXPLOSIONSPIRITS: {
|
|
while (this->HasId(0xCB)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xCB, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0xCB, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
while (this->HasId(0xA6)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA6, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFE, 0x80, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_STEELBODY:
|
|
case EFST_DBARRIER: {
|
|
while (this->HasId(0xFE)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xFE, 0, 0, 0, 0, 0);
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x46C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (this->render.accountId == g_session.m_gid || IsPlayerJob(this->GetEffectiveJob(-1))) {
|
|
CPc* pc = static_cast<CPc*>(this);
|
|
pc->virtue = on ? pc->virtue | 0x10 : pc->virtue ^ 0x10;
|
|
if ((pc->virtue & 0x10) == 0 && (pc->appearanceFlags & 0x10) == 0) {
|
|
break;
|
|
}
|
|
} else if (!on) {
|
|
break;
|
|
}
|
|
this->LaunchEffect(0xFE, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x46C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_SG_SUN_WARM:
|
|
case EFST_SG_MOON_WARM:
|
|
case EFST_SG_STAR_WARM:
|
|
while (this->HasId(0x1A2)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1A2, 0, 0, 0, 0, 0);
|
|
}
|
|
while (this->HasId(0x220)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x220, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x1A2, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x220, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DAURA:
|
|
while (this->HasId(0x1A2)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1A2, 0, 0, 0, 0, 0);
|
|
}
|
|
while (this->HasId(0x220)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x220, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x1A2, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x220, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_KAITE:
|
|
while (this->HasId(0x1A3)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1A3, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x1A3, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_AURABLADE:
|
|
while (this->HasId(0x16F)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x16F, 0, 0, 0, 0, 0);
|
|
}
|
|
while (this->HasId(0x1DA)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1DA, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x16F, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x1DA, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_STOP:
|
|
while (this->HasId(0x1C5)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1C5, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_MOON: {
|
|
while (this->HasId(0x18A)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18A, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x18A, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MARIONETTE_MASTER: {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18B, 0, 0, 0, 0, 0);
|
|
while (this->HasId(0x18C)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x18C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MARIONETTE: {
|
|
while (this->HasId(0x18C)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x18C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_LKCONCENTRATION: {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x171, 0, 0, 0, 0, 0);
|
|
if (on) {
|
|
this->LaunchEffect(0x171, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_BERSERK: {
|
|
while (this->HasId(0x170)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x170, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x170, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_RG_CCONFINE_M:
|
|
case EFST_RG_CCONFINE_S: {
|
|
while (this->HasId(0x25C)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x25C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x25C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_WZ_SIGHTBLASTER: {
|
|
while (this->HasId(0x259)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x259, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x259, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_POWERUP: {
|
|
while (this->HasId(0x1C7)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1C7, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x1C7, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_RUN: {
|
|
if (this->HasId(0x1BA)) {
|
|
this->LaunchEffect(0x1BB, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1BA, 0, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
case EFST_TING: {
|
|
const vector3d& player = reinterpret_cast<const CRenderObject*>(static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player)->render.position;
|
|
g_soundMgr->PlayWave("effect\\T_벽튕김.wav", this->render.position.x - player.x, 0.0f, this->render.position.z - player.z, 250, 40, 1.0f, 0);
|
|
this->LaunchEffect(0x1AA, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (this->HasId(0x1BA)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1BA, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MAGICPOWER: {
|
|
while (this->HasId(0x17E)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x17E, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x17E, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_OVERTHRUST:
|
|
case EFST_OVERTHRUSTMAX: {
|
|
while (this->HasId(0xA6)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA6, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0x80, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_ENERGYCOAT: {
|
|
while (this->HasId(0xA6)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA6, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0xA9, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_TRICKDEAD:
|
|
if (on) {
|
|
this->isTrickDead = 1;
|
|
if (this->GetMonsterTransformJob() > 0) {
|
|
this->SetAction(0x20, 4, 1);
|
|
} else {
|
|
this->SetAction(this->WeaponActionBase(3), 4, 1);
|
|
}
|
|
this->render.isMotionFreezed = true;
|
|
} else {
|
|
this->isTrickDead = 0;
|
|
this->render.state = 0;
|
|
this->render.isLieOnGround = false;
|
|
this->render.visibilityOptions[1] = 1;
|
|
this->SetState(0, 1);
|
|
this->render.isMotionFreezed = false;
|
|
}
|
|
break;
|
|
case EFST_ILLUSION:
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
if (on) {
|
|
g_screenShakeDuration = 10000;
|
|
g_screenShakeMode = 2;
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
if (gameMode) {
|
|
gameMode->camera->frame.up[0] = 0.0f;
|
|
gameMode->camera->frame.up[1] = -1.0f;
|
|
gameMode->camera->frame.up[2] = 0.0f;
|
|
}
|
|
} else {
|
|
g_screenShakeDuration = 0;
|
|
CGameMode* gameMode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
|
|
if (gameMode) {
|
|
gameMode->camera->frame.up[0] = 0.0f;
|
|
gameMode->camera->frame.up[1] = 1.0f;
|
|
gameMode->camera->frame.up[2] = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EFST_RICHMANKIM: {
|
|
if (this->HasId(0x363) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x363, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x363, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_WHISTLE:
|
|
case EFST_HUMMING:
|
|
case EFST_INTOABYSS: {
|
|
if (this->HasId(0x361) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x361, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x361, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_RINGNIBELUNGEN:
|
|
case EFST_SIEGFRIED: {
|
|
if (this->HasId(0x36B) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x36B, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x36B, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_APPLEIDUN: {
|
|
if (this->HasId(0x35D) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x35D, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x35D, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_ETERNALCHAOS:
|
|
case EFST_ROKISWEIL: {
|
|
if (this->HasId(0x360) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x360, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x360, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_ASSASSINCROSS:
|
|
case EFST_SERVICEFORYOU: {
|
|
if (this->HasId(0x369) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x369, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x369, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_FORTUNEKISS:
|
|
case EFST_DRUMBATTLEFIELD: {
|
|
if (this->HasId(0x367) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x367, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x367, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_DONTFORGETME: {
|
|
if (this->HasId(0x26) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x26, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x26, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_POEMBRAGI: {
|
|
if (this->HasId(0x36D) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x36D, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x36D, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_DA_CONTRACT: {
|
|
while (this->HasId(0x24A)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x24A, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x24A, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_DUPLELIGHT: {
|
|
while (this->HasId(0x341)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x341, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0x341, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
vector3d scale{2.0f, 0.0f, 0.0f};
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETPOS, 0, reinterpret_cast<int>(&scale), 0, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_ORATIO:
|
|
while (this->HasId(0x2F3)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x2F3, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x2F3, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_BLOOD_SUCKER:
|
|
while (this->HasId(0x170)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x170, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x170, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_BANDING:
|
|
if (on) {
|
|
if (!this->HasId(0x38D)) {
|
|
this->LaunchEffect(0x38D, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_CURSEDCIRCLE_ATKER:
|
|
case EFST_CURSEDCIRCLE_TARGET: {
|
|
unsigned char shade;
|
|
bool frozen;
|
|
if (on) {
|
|
shade = 0x40;
|
|
frozen = true;
|
|
} else {
|
|
shade = 0xFF;
|
|
frozen = false;
|
|
}
|
|
unsigned char* const argb = reinterpret_cast<unsigned char*>(&this->render.color);
|
|
this->render.isMotionFreezed = frozen;
|
|
this->render.colorLocked = frozen;
|
|
argb[2] = shade;
|
|
argb[1] = shade;
|
|
argb[0] = shade;
|
|
break;
|
|
}
|
|
case EFST_STRIKING:
|
|
if (IsPlayerJob(this->GetEffectiveJob(-1))) {
|
|
while (this->HasId(0x39D)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x39D, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
CRagEffect* effect = this->LaunchEffect(0x39D, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0x39D, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EFST_VENOMIMPRESS:
|
|
while (this->HasId(0x314)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x314, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x314, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_FROSTMISTY:
|
|
while (this->HasId(0x315)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x315, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x315, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_COLD:
|
|
while (this->HasId(0x3AC)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3AC, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x3AC, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SUMMON1:
|
|
this->SetTetraBall(0, static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case EFST_SUMMON2:
|
|
this->SetTetraBall(1, static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case EFST_SUMMON3:
|
|
this->SetTetraBall(2, static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case EFST_SUMMON4:
|
|
this->SetTetraBall(3, static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case EFST_SUMMON5:
|
|
this->SetTetraBall(4, static_cast<int>(c), static_cast<int>(d));
|
|
break;
|
|
case EFST_ROLLINGCUTTER:
|
|
if (c == 1) {
|
|
const std::int64_t level = d;
|
|
if (level <= 10 && level > 0) {
|
|
for (int id = 0x514; id < 0x51E; ++id) {
|
|
g_effectMgr->Retire(this->render.accountId, id);
|
|
g_effectMgr->Retire(this->render.accountId, id + 0xA7);
|
|
}
|
|
if (g_serviceOptions.Get(0xE5)) {
|
|
g_effectMgr->Spawn(this->render.accountId, static_cast<int>(d) + 0x5BA, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Spawn(this->render.accountId, static_cast<int>(d) + 0x513, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
}
|
|
} else {
|
|
for (int id = 0x514; id < 0x51E; ++id) {
|
|
g_effectMgr->Retire(this->render.accountId, id);
|
|
g_effectMgr->Retire(this->render.accountId, id + 0xA7);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_SIREN:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x36F, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x36F, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x36F, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_SONG_OF_MANA:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x361, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x361, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DANCE_WITH_WUG:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x363, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x363, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_LERADS_DEW:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x367, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x367, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DEEP_SLEEP:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_MAKE_SLEEP_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_SLEEP_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_NETHERWORLD:
|
|
while (this->HasId(0x1C5)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1C5, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x1C5, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_CAMOUFLAGE:
|
|
while (this->HasId(0x2E8)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x2E8, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x2E8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
if (this->hpGaugeWindow) {
|
|
if (on) {
|
|
reinterpret_cast<UIMonsterGage*>(this->hpGaugeWindow)->SetMode(0);
|
|
} else {
|
|
reinterpret_cast<UIMonsterGage*>(this->hpGaugeWindow)->SetMode(1);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_MANHOLE:
|
|
while (this->HasId(0x337)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x337, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
g_soundMgr->PlayWave("effect\\manhole.wav", 0.0f, 0.0f, 0.0f, 250, 40, 1.0f, 0);
|
|
if (!g_session.IsMonsterClass(this->GetEffectiveJob(-1))) {
|
|
this->LaunchEffect(0x337, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_SHADOWFORM:
|
|
while (this->HasId(0x329)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x329, 0, 0, 0, 0, 0);
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x333, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x329, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_STEALTHFIELD:
|
|
while (this->HasId(0x2E8)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x2E8, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x2E8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_WUGDASH:
|
|
while (this->HasId(0x2F0)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x2F0, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x2F0, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DA_BLACK:
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
g_screenShakeDuration = 1;
|
|
g_screenShakeMode = 1;
|
|
}
|
|
break;
|
|
case EFST_MER_FLEE: {
|
|
const int text = reinterpret_cast<int>("FLEE UP!");
|
|
this->SendMsg(nullptr, AM_CHAT, text, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x1C8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_MER_ATK: {
|
|
const int text = reinterpret_cast<int>("ATK UP!");
|
|
this->SendMsg(nullptr, AM_CHAT, text, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x1C8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_MER_HIT: {
|
|
const int text = reinterpret_cast<int>("DEX UP!");
|
|
this->SendMsg(nullptr, AM_CHAT, text, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x1C8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_MER_HP: {
|
|
const int text = reinterpret_cast<int>("HP UP!");
|
|
this->SendMsg(nullptr, AM_CHAT, text, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x1C8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_MER_SP: {
|
|
const int text = reinterpret_cast<int>("SP UP!");
|
|
this->SendMsg(nullptr, AM_CHAT, text, 0, 0, 0, 0, 0);
|
|
this->LaunchEffect(0x1C8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
break;
|
|
}
|
|
case EFST_UNLIMITED_HUMMING_VOICE:
|
|
if (this->HasId(0x361) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x361, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x361, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_MELODYOFSINK:
|
|
if (this->HasId(0x57) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x57, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x57, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_BEYOND_OF_WARCRY:
|
|
if (this->HasId(0x31F) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x31F, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x31F, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SATURDAY_NIGHT_FEVER:
|
|
if (this->HasId(0x360) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x360, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
this->LaunchEffect(0x360, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_PAIN_KILLER:
|
|
case EFST_LIGHT_OF_REGENE:
|
|
case EFST_OVERED_BOOST:
|
|
case EFST_STYLE_CHANGE:
|
|
case EFST_MAGMA_FLOW:
|
|
case EFST_PYROCLASTIC:
|
|
case EFST_VOLCANIC_ASH:
|
|
case EFST_OVERLAPEXPUP:
|
|
case EFST_EQUIPPED_DIVINE_ARMOR:
|
|
case EFST_EQUIPPED_HOLY_ARMOR:
|
|
break;
|
|
case EFST_EQUIPED_FLOOR:
|
|
g_effectMgr->SpawnLevel99(this, on, static_cast<int>(d));
|
|
break;
|
|
case EFST_GRANITIC_ARMOR:
|
|
while (this->HasId(0x3C3)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3C3, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3C3, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_ALL_RIDING: {
|
|
if (this->render.state == 25) {
|
|
this->SetState(0, 1);
|
|
}
|
|
int job;
|
|
if (c > 0) {
|
|
this->SetRiding(1);
|
|
job = this->GetEffectiveJob(-1);
|
|
} else {
|
|
this->SetRiding(0);
|
|
job = JobNames::BaseJob(this->GetEffectiveJob(-1));
|
|
}
|
|
this->SetActorJob(job);
|
|
this->SetBodyPalette(this->render.bodyPalette);
|
|
this->SetSprRobe(0, 1);
|
|
break;
|
|
}
|
|
case EFST_MONSTER_TRANSFORM:
|
|
case EFST_KYOUGAKU:
|
|
case EFST_ACTIVE_MONSTER_TRANSFORM: {
|
|
int slot;
|
|
switch (b) {
|
|
case EFST_MONSTER_TRANSFORM:
|
|
slot = 0;
|
|
break;
|
|
case EFST_KYOUGAKU:
|
|
slot = 1;
|
|
break;
|
|
case EFST_ACTIVE_MONSTER_TRANSFORM:
|
|
slot = 2;
|
|
break;
|
|
default:
|
|
slot = 0;
|
|
break;
|
|
}
|
|
if (c != 0) {
|
|
this->SetTransformJob(static_cast<int>(d), slot);
|
|
} else {
|
|
this->SetTransformJob(-1, slot);
|
|
if (this->render.state == 3) {
|
|
this->SetAction(this->WeaponActionBase(3), 4, 1);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EFST_KO_JYUMONJIKIRI:
|
|
g_effectMgr->Retire(this->render.accountId, 0x3E6);
|
|
if (c != 0 && g_effectMgr->HasAllocator(0x3E6)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x3E6, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_KYOMU:
|
|
while (this->HasId(0x3C3)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3C3, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3C3, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_KAGEMUSYA:
|
|
while (this->HasId(0x3EC)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3EC, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3EC, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_MEIKYOUSISUI:
|
|
while (this->HasId(0x18A)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18A, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
CRagEffect* effect = this->LaunchEffect(0x18A, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (effect) {
|
|
effect->state.colorChannels[0] = 180;
|
|
effect->state.colorChannels[1] = 180;
|
|
effect->state.colorChannels[2] = -1;
|
|
}
|
|
}
|
|
break;
|
|
case EFST_ZANGETSU:
|
|
while (this->HasId(0x3EB)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3EB, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3EB, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_GENSOU:
|
|
g_effectMgr->Retire(this->render.accountId, 0x3ED);
|
|
if (c != 0 && g_effectMgr->HasAllocator(0x3ED)) {
|
|
CEffect* orb = g_effectMgr->Spawn(this->render.accountId, 0x3ED, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
if (orb) {
|
|
static_cast<CEnergyOrbEffect*>(orb)->SetCount(10);
|
|
}
|
|
}
|
|
while (this->HasId(0x3C3)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3C3, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3C3, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_AKAITSUKI:
|
|
while (this->HasId(0x220)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x220, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x220, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SHOW_HP:
|
|
this->hasHp = c != 0;
|
|
break;
|
|
case EFST_HAT_EFFECT:
|
|
this->SetStackedEffect(0x3F4, c > 0);
|
|
break;
|
|
case EFST_MOONSTAR:
|
|
this->SetStackedEffect(0x40A, c > 0);
|
|
break;
|
|
case EFST_DECORATION_OF_MUSIC:
|
|
this->SetStackedEffect(0x437, c > 0);
|
|
break;
|
|
case EFST_STRANGELIGHTS:
|
|
this->SetStackedEffect(0x40B, c > 0);
|
|
break;
|
|
case EFST_SUPER_STAR:
|
|
this->SetStackedEffect(0x40C, c > 0);
|
|
break;
|
|
case EFST_ON_PUSH_CART:
|
|
if (c != 0) {
|
|
if (static_cast<std::int64_t>(this->maxHp) == d) {
|
|
break;
|
|
}
|
|
this->maxHp = static_cast<int>(d);
|
|
if (StateFlag01(this->stateFlags) || StateFlag02(this->stateFlags) || StateFlag06(this->stateFlags)) {
|
|
break;
|
|
}
|
|
this->SendMsg(nullptr, AM_DELETE_CART, 0, 0, 0, 0, 0, 0);
|
|
this->SendMsg(nullptr, AM_MAKE_CART, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
this->maxHp = 0;
|
|
this->SendMsg(nullptr, AM_DELETE_CART, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_FLOWER_LEAF:
|
|
if (c != 0) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x3F5, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x3F5);
|
|
}
|
|
break;
|
|
case EFST_RAY_OF_PROTECTION:
|
|
while (this->HasId(0x3FB)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x3FB, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x3FB, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_CLAN_INFO:
|
|
this->hasSp = e != 0;
|
|
this->spGaugeValue = static_cast<int>(e);
|
|
break;
|
|
case EFST_HANDICAPSTATE_ICEEXPLO:
|
|
if (c != 0) {
|
|
this->SendMsg(nullptr, AM_CHANGE_COLOR, 50, 150, 255, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_MAXPAIN:
|
|
while (this->HasId(0x40D)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x40D, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x40D, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_DARKCROW:
|
|
while (this->HasId(0x410)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x410, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x410, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x410, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
this->LaunchEffect(0x410, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_TELEKINESIS_INTENSE:
|
|
while (this->HasId(0x418)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x418, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x418, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_ILLUSIONDOPING:
|
|
while (this->HasId(0x419)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x419, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x419, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_WIDEWEB:
|
|
while (this->HasId(0x194)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x194, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x194, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_BURNT:
|
|
while (this->HasId(0x41E)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x41E, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x41E, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_CHILL:
|
|
while (this->HasId(0x41F)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x41F, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x41F, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_OFFERTORIUM:
|
|
while (this->HasId(0x421)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x421, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on) {
|
|
this->LaunchEffect(0x421, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_C_MARKER:
|
|
this->SendMsg(this, AM_DELETE_EFFECT, 0x433, 0, 0, 0, 0, 0);
|
|
if (on) {
|
|
if (g_session.actorEffectStates.find(static_cast<int>(this->render.accountId)) == g_session.actorEffectStates.end() && g_effectMgr->HasAllocator(0x425)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x425, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
if (g_effectMgr->HasAllocator(0x433)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x433, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_ANTI_M_BLAST:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x470, this->render.position, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x470);
|
|
}
|
|
break;
|
|
case EFST_E_QD_SHOT_READY:
|
|
g_effectMgr->Spawn(0, 0x434, this->render.position, 0, -1, 0, 0);
|
|
break;
|
|
case EFST_H_MINE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x473, this->render.position, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x473);
|
|
}
|
|
break;
|
|
case EFST_H_MINE_SPLASH:
|
|
if (on) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x425, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Spawn(0, 0x432, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_FLOWERSMOKE:
|
|
this->SetStackedEffect(0x43B, c > 0);
|
|
break;
|
|
case EFST_HALLUCINATIONWALK:
|
|
case EFST_NPC_HALLUCINATIONWALK: {
|
|
while (this->HasId(0x318)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x318, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c == 0) {
|
|
break;
|
|
}
|
|
CRagEffect* effect = this->LaunchEffect(0x318, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
if (!effect) {
|
|
break;
|
|
}
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0x318, 0, 0, 0);
|
|
break;
|
|
}
|
|
case EFST_SOULLINK:
|
|
case EFST_SOULSHADOW:
|
|
case EFST_SOULFAIRY:
|
|
case EFST_SOULFALCON:
|
|
case EFST_SOULGOLEM:
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
if (c != 0) {
|
|
g_weatherEffect.StartDarken();
|
|
break;
|
|
}
|
|
g_weatherEffect.StopDarken();
|
|
} else if (c != 0) {
|
|
break;
|
|
}
|
|
while (this->HasId(0x1A8)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x1A8, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_HAPPINESS_STAR:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x43F, true);
|
|
} else {
|
|
this->SetStackedEffect(0x43F, false);
|
|
}
|
|
break;
|
|
case EFST_FSTONE:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x43C, true);
|
|
} else {
|
|
this->SetStackedEffect(0x43C, false);
|
|
}
|
|
break;
|
|
case EFST_QSCARABA:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x43D, true);
|
|
} else {
|
|
this->SetStackedEffect(0x43D, false);
|
|
}
|
|
break;
|
|
case EFST_LJOSALFAR:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x43E, true);
|
|
} else {
|
|
this->SetStackedEffect(0x43E, false);
|
|
}
|
|
break;
|
|
case EFST_MAPLE_FALLS:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x441, true);
|
|
} else {
|
|
this->SetStackedEffect(0x441, false);
|
|
}
|
|
break;
|
|
case EFST_DRESS_UP:
|
|
g_session.playerAppearanceState = g_session.m_aid == this->render.accountId ? static_cast<int>(d) : g_session.playerAppearanceState;
|
|
this->mountedState = static_cast<int>(d);
|
|
this->SetSprJob(this->GetEffectiveJob(-1));
|
|
this->SetImfFileName();
|
|
this->SetHeadPaletteName();
|
|
this->SetBodyPaletteName();
|
|
break;
|
|
case EFST_MARKING_USE_CHANGEMONSTER:
|
|
if (c != 0) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x442, this->render.position, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x442);
|
|
}
|
|
break;
|
|
case EFST_MAGICAL_FEATHER:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x443, true);
|
|
} else {
|
|
this->SetStackedEffect(0x443, false);
|
|
}
|
|
break;
|
|
case EFST_MERMAID_LONGING:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x444, true);
|
|
} else {
|
|
this->SetStackedEffect(0x444, false);
|
|
}
|
|
break;
|
|
case EFST_TIME_ACCESSORY:
|
|
if (c > 0) {
|
|
this->SetStackedEffect(0x447, true);
|
|
} else {
|
|
this->SetStackedEffect(0x447, false);
|
|
}
|
|
break;
|
|
case EFST_HEAD_EQUIPMENT_EFFECT:
|
|
this->SetStackedEffect(static_cast<int>(d) + 0x9B5, c > 0);
|
|
break;
|
|
case EFST_SPRITEMABLE:
|
|
g_effectMgr->Retire(this->render.accountId, 0x448);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x448, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_SUHIDE:
|
|
if (on == true) {
|
|
this->SetState(0x30, 1);
|
|
this->render.isMotionFreezed = true;
|
|
this->render.specialMotionLocked = 1;
|
|
} else {
|
|
this->render.state = 0;
|
|
this->render.isLieOnGround = false;
|
|
this->render.visibilityOptions[1] = 1;
|
|
this->SetState(0, 1);
|
|
this->render.isMotionFreezed = false;
|
|
this->render.specialMotionLocked = 0;
|
|
}
|
|
break;
|
|
case EFST_SU_STOOP:
|
|
if (on == true) {
|
|
this->SetState(0x2F, 1);
|
|
} else if (this->render.specialMotionLocked == 0) {
|
|
this->SetState(0, 1);
|
|
}
|
|
break;
|
|
case EFST_TUNAPARTY:
|
|
if (on == true) {
|
|
if (!g_effectMgr->Has(this->render.accountId, 0x449)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x449, this->render.position, 0, -1, 0, 0);
|
|
}
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x449);
|
|
}
|
|
break;
|
|
case EFST_SV_ROOTTWIST:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x456, this->render.position, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x456);
|
|
}
|
|
break;
|
|
case EFST_BITESCAR:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x45F, this->render.position, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x45F);
|
|
}
|
|
break;
|
|
case EFST_SOULATTACK:
|
|
if (g_session.IsDoramJob(this->GetEffectiveJob(-1))) {
|
|
static_cast<CPc*>(this)->alternateDoramAppearance[0] = on;
|
|
}
|
|
break;
|
|
case EFST_IMMUNE_PROPERTY_NOTHING:
|
|
case EFST_IMMUNE_PROPERTY_WATER:
|
|
case EFST_IMMUNE_PROPERTY_GROUND:
|
|
case EFST_IMMUNE_PROPERTY_FIRE:
|
|
case EFST_IMMUNE_PROPERTY_WIND:
|
|
case EFST_IMMUNE_PROPERTY_POISON:
|
|
case EFST_IMMUNE_PROPERTY_SAINT:
|
|
case EFST_IMMUNE_PROPERTY_DARKNESS:
|
|
case EFST_IMMUNE_PROPERTY_TELEKINESIS:
|
|
case EFST_IMMUNE_PROPERTY_UNDEAD: {
|
|
const int effectId = static_cast<int>(b) + 0x87;
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, effectId, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (g_effectMgr->Has(this->render.accountId, effectId) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, effectId);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_GRAVITYCONTROL: {
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4B1) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4B1);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4B1, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
const vector3d& player =
|
|
reinterpret_cast<const CRenderObject*>(static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player)->render.position;
|
|
g_soundMgr->PlayWave(
|
|
"effect\\t_캐스팅.wav", this->render.position.x - player.x, 0.0f,
|
|
this->render.position.z - player.z, 250, 40, 1.0f, 0
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_SUNSTANCE:
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4BE) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4BE);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4BE, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_LUNARSTANCE:
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4BF) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4BF);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4BF, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_STARSTANCE:
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4C0) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4C0);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4C0, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_UNIVERSESTANCE:
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4C1) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4C1);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4C1, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_FLASHKICK:
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4C5) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4C5);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4C5, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_SOULUNITY: {
|
|
if (g_effectMgr->Has(this->render.accountId, 0x4C6) == true) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x4C6);
|
|
}
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x4C6, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
const vector3d& player =
|
|
reinterpret_cast<const CRenderObject*>(static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player)->render.position;
|
|
g_soundMgr->PlayWave(
|
|
"effect\\t_바람방출.wav", this->render.position.x - player.x, 0.0f,
|
|
this->render.position.z - player.z, 250, 40, 1.0f, 0
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_ASSUMPTIO:
|
|
case EFST_ASSUMPTIO2:
|
|
case EFST_ASSUMPTIO_BUFF:
|
|
while (this->HasId(0x177)) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x177, 0, 0, 0, 0, 0);
|
|
}
|
|
if (c != 0) {
|
|
this->LaunchEffect(0x177, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SOULCURSE:
|
|
if (c == 1) {
|
|
if (g_effectMgr->Find(this->render.accountId, 0x552)) {
|
|
break;
|
|
}
|
|
g_effectMgr->Spawn(this->render.accountId, 0x552, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
g_soundMgr->PlayWave("effect\\s포이즌버스터.wav", 0.0f, 0.0f, 0.0f, 250, 40, 1.0f, 0);
|
|
} else {
|
|
CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x552);
|
|
if (effect) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_SOUND_OF_DESTRUCTION: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (!actor) {
|
|
break;
|
|
}
|
|
g_effectMgr->Retire(actor->render.accountId, 0x66C);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(actor->render.accountId, 0x66C, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_EARTHSHAKER: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (actor->HasId(0x576)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x576, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x576, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MAGIC_POISON: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (actor->HasId(0x18C)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x18C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x18C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MISTY_FROST: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (actor->HasId(0x58C)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x58C, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x58C, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_PRISON: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (actor->HasId(0x5F5)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x5F5, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x5F5, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_MADOGEAR_TYPE: {
|
|
CGameActor* target = this;
|
|
if (this->render.accountId != g_session.m_aid) {
|
|
target = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(this->render.accountId));
|
|
}
|
|
if (!target) {
|
|
break;
|
|
}
|
|
if (c == 1) {
|
|
if (d == 2) {
|
|
target->SetMadogearType(2);
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
g_session.madogearType = 2;
|
|
}
|
|
} else {
|
|
target->SetMadogearType(1);
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
g_session.madogearType = 1;
|
|
}
|
|
}
|
|
target->SendMsg(nullptr, AM_MAKE_CHICKEN, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
target->SetMadogearType(0);
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
g_session.madogearType = 0;
|
|
}
|
|
target->SendMsg(nullptr, AM_DELETE_CHICKEN, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_RELIEVE_DAMAGE: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (!actor) {
|
|
break;
|
|
}
|
|
g_effectMgr->Retire(actor->render.accountId, 0x63F);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(actor->render.accountId, 0x63F, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_LOCKON_LASER: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (!actor) {
|
|
break;
|
|
}
|
|
if (actor->HasId(0x641)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x641, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x641, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_HELLS_PLANT_ARMOR: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (!actor) {
|
|
break;
|
|
}
|
|
if (actor->HasId(0x64A)) {
|
|
actor->SendMsg(nullptr, AM_DELETE_EFFECT, 0x64A, 0, 0, 0, 0, 0);
|
|
}
|
|
if (on == true) {
|
|
actor->LaunchEffect(0x64A, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_HANDICAPSTATE_DEEPBLIND:
|
|
if (this->render.accountId != g_session.m_aid) {
|
|
break;
|
|
}
|
|
if (c == 1) {
|
|
if (!this->HasId(0x14E)) {
|
|
this->LaunchEffect(0x14E, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
g_overrideColor = 1;
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0xA4, 0, 0, 0, 0, 0);
|
|
CPlayer* const player = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player;
|
|
if (player) {
|
|
player->skillEffect = this->LaunchEffect(0xA4, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
} else {
|
|
if (this->HasId(0x14E) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x14E, 0, 0, 0, 0, 0);
|
|
}
|
|
g_overrideColor = 0;
|
|
}
|
|
this->SetInstantValue(0x10, on);
|
|
break;
|
|
case EFST_HANDICAPSTATE_DEEPSILENCE:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_MAKE_DEEPSILENCE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_DEEPSILENCE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_SWOONING:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_MAKE_DEEPSILENCE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Retire(this->render.accountId, 0x8C5);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8C5, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_DEEPSILENCE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Retire(this->render.accountId, 0x8C5);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_LASSITUDE:
|
|
if (c == 1) {
|
|
this->SendMsg(nullptr, AM_MAKE_LASSITUDE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8C4, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_LASSITUDE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_FROSTBITE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8DE, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (g_effectMgr->Has(this->render.accountId, 0x8DE)) {
|
|
g_effectMgr->Retire(this->render.accountId, 0x8DE);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8DF, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
if (this->render.accountId == g_session.m_aid) {
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8E0, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x8E0);
|
|
}
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_LIGHTNINGSTRIKE:
|
|
g_effectMgr->Retire(this->render.accountId, 0x8DC);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8DC, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_CRYSTALLIZATION:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8E1, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x8E1);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_HOLYFLAME:
|
|
if (on == true) {
|
|
this->SendMsg(nullptr, AM_CHANGE_COLOR, 0xFF, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8C6, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_RETURN_COLOR, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
this->SetInstantValue(0xC, on);
|
|
break;
|
|
case EFST_HANDICAPSTATE_CONFLAGRATION:
|
|
if (on == true) {
|
|
this->SendMsg(nullptr, AM_CHANGE_COLOR, 0xFF, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Retire(this->render.accountId, 0x8DD);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8DD, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_RETURN_COLOR, 0, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Retire(this->render.accountId, 0x8DD);
|
|
}
|
|
this->SetInstantValue(0xD, on);
|
|
break;
|
|
case EFST_HANDICAPSTATE_MISFORTUNE:
|
|
if (on == true) {
|
|
this->SendMsg(nullptr, AM_MAKE_MISFORTUNE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_DELETE_MISFORTUNE_EFFECT, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_HANDICAPSTATE_DEADLYPOISON:
|
|
if (on == true) {
|
|
this->SendMsg(nullptr, AM_CHANGE_COLOR, 0xAA, 0, 0xAA, 0, 0, 0);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8E2, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_RETURN_COLOR, 0, 0, 0, 0, 0, 0);
|
|
g_effectMgr->Retire(this->render.accountId, 0x8E2);
|
|
}
|
|
this->SetInstantValue(0xE, on);
|
|
break;
|
|
case EFST_HANDICAPSTATE_DEPRESSION:
|
|
if (on == true) {
|
|
this->SendMsg(nullptr, AM_CHANGE_COLOR, 0, 0, 0xFF, 0, 0, 0);
|
|
} else {
|
|
this->SendMsg(nullptr, AM_RETURN_COLOR, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
this->SetInstantValue(0xF, on);
|
|
break;
|
|
case EFST_DRAGONIC_AURA: {
|
|
CGameActor* actor = this;
|
|
if (actor->render.accountId != g_session.m_aid) {
|
|
actor = static_cast<CGameActor*>(mode->scene->GetGameActorByAID(actor->render.accountId));
|
|
}
|
|
if (!actor) {
|
|
break;
|
|
}
|
|
g_effectMgr->Retire(actor->render.accountId, 0x6BE);
|
|
g_effectMgr->Retire(actor->render.accountId, 0x6BF);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(actor->render.accountId, 0x6BE, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
g_effectMgr->Spawn(actor->render.accountId, 0x6BF, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_FIRST_BRAND: {
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x806, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
CEffect* const second = g_effectMgr->Spawn(this->render.accountId, 0x803, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
CEffect* const third = g_effectMgr->Spawn(this->render.accountId, 0x804, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
if (second) {
|
|
second->SetDelay(1000);
|
|
}
|
|
if (third) {
|
|
third->SetDelay(1000);
|
|
}
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x803);
|
|
g_effectMgr->Retire(this->render.accountId, 0x804);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_SECOND_BRAND: {
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x821, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
CEffect* const second = g_effectMgr->Spawn(this->render.accountId, 0x81e, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
CEffect* const third = g_effectMgr->Spawn(this->render.accountId, 0x81f, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
if (second) {
|
|
second->SetDelay(1000);
|
|
}
|
|
if (third) {
|
|
third->SetDelay(1000);
|
|
}
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x821);
|
|
g_effectMgr->Retire(this->render.accountId, 0x81e);
|
|
g_effectMgr->Retire(this->render.accountId, 0x81f);
|
|
}
|
|
break;
|
|
}
|
|
case EFST_HOLY_OIL:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7c7, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x7c7);
|
|
}
|
|
break;
|
|
case EFST_MEDIALE:
|
|
if (on == true) {
|
|
if (!g_serviceOptions.Get(0xe5) && !g_effectMgr->Find(this->render.accountId, 0x712)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x712, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x712);
|
|
}
|
|
break;
|
|
case EFST_DEADLY_DEFEASANCE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x6cd, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x6cd)) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
break;
|
|
case EFST_CLIMAX:
|
|
g_effectMgr->Retire(this->render.accountId, 0x708);
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x708, this->render.position, 0, static_cast<int>(d), 0, 0);
|
|
}
|
|
break;
|
|
case EFST_FIRST_FAITH_POWER:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7b7, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x7b7);
|
|
}
|
|
break;
|
|
case EFST_SECOND_JUDGE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7ba, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7bd, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x7ba);
|
|
g_effectMgr->Retire(this->render.accountId, 0x7bd);
|
|
}
|
|
break;
|
|
case EFST_THIRD_EXOR_FLAME:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7be, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x7c1, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x7be);
|
|
g_effectMgr->Retire(this->render.accountId, 0x7c1);
|
|
}
|
|
break;
|
|
case EFST_ABYSS_SLAYER:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x84e, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x84e);
|
|
}
|
|
break;
|
|
case EFST_D_MACHINE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x719, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
this->LaunchEffect(0x8f8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x719)) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
break;
|
|
case EFST_A_MACHINE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x72f, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x72f);
|
|
}
|
|
break;
|
|
case EFST_COMPETENTIA:
|
|
if (on == true) {
|
|
if (!g_effectMgr->Find(this->render.accountId, 0x73d)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x73d, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
if (!g_serviceOptions.Get(0xe5) && !g_effectMgr->Find(this->render.accountId, 0x73c)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x73c, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
this->LaunchEffect(0x8fc, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else {
|
|
if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x73d)) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
if (!g_serviceOptions.Get(0xe5)) {
|
|
if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x73c)) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EFST_CLIMAX_CRYIMP:
|
|
if (on == true) {
|
|
if (!g_effectMgr->Find(this->render.accountId, 0x743)) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x743, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x743);
|
|
}
|
|
break;
|
|
case EFST_SOUNDBLEND:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x80c, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x80c)) {
|
|
g_effectMgr->Retire(effect, 1);
|
|
}
|
|
break;
|
|
case EFST_WINDSIGN:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x76c, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x76c);
|
|
}
|
|
break;
|
|
case EFST_E_SLASH_COUNT:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x779, this->render.position, 0, static_cast<int>(d), 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x779);
|
|
}
|
|
break;
|
|
case EFST_ELEMENTAL_VEIL:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x2e8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else if (this->HasId(0x2e8) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x2e8, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_BO_HELL_DUSTY:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8be, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_CLOUD_POISON:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8e5, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else if (this->HasId(0x8e5) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x8e5, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_SPORE_EXPLOSION_DEBUFF:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8e6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
} else if (this->HasId(0x8e6) == true) {
|
|
this->SendMsg(nullptr, AM_DELETE_EFFECT, 0x8e6, 0, 0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_FIRM_FAITH:
|
|
case EFST_MUSICAL_INTERLUDE:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8f8, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_POWERFUL_FAITH:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8f6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_SPELL_ENCHANTING:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8fa, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_PRE_ACIES:
|
|
if (on == true) {
|
|
this->LaunchEffect(0x8f0, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
|
|
}
|
|
break;
|
|
case EFST_KILLING_AURA:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8fe, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else {
|
|
g_effectMgr->Retire(this->render.accountId, 0x8fe);
|
|
g_effectMgr->Spawn(this->render.accountId, 0x8ff, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
}
|
|
break;
|
|
case EFST_CURSE_R_CUBE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x901, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x901)) {
|
|
static_cast<CCurseOfCubeEffect*>(effect)->Restart();
|
|
}
|
|
break;
|
|
case EFST_CURSE_B_CUBE:
|
|
if (on == true) {
|
|
g_effectMgr->Spawn(this->render.accountId, 0x902, vector3d{0.0f, 0.0f, 0.0f}, 0, -1, 0, 0);
|
|
} else if (CEffect* const effect = g_effectMgr->Find(this->render.accountId, 0x902)) {
|
|
static_cast<CCurseOfCubeEffect*>(effect)->Restart();
|
|
}
|
|
break;
|
|
case EFST_BLOCK:
|
|
if (on == true) {
|
|
g_windowMgr.EnsureWindow(WID_DEBUFFREMOVEWND);
|
|
} else {
|
|
g_windowMgr.CloseWindow(WID_DEBUFFREMOVEWND);
|
|
}
|
|
break;
|
|
default:
|
|
if (on == true) {
|
|
CSkillActionMgr::GetInstance()->OnEfstBegin(static_cast<int>(b), static_cast<int>(d), static_cast<int>(e), static_cast<int>(g), this, f != 0);
|
|
} else {
|
|
CSkillActionMgr::GetInstance()->OnEfstEnd(static_cast<int>(b), static_cast<int>(d), static_cast<int>(e), static_cast<int>(g), this);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case AM_CHANGE_COLOR: {
|
|
this->render.colorLocked = 1;
|
|
unsigned char* const saved = reinterpret_cast<unsigned char*>(&this->render.savedTintColor);
|
|
if (saved[0] == 0 && saved[1] == 0 && saved[2] == 0 && saved[3] == 0) {
|
|
const unsigned char* const argb = reinterpret_cast<const unsigned char*>(&this->render.color);
|
|
saved[0] = argb[3];
|
|
saved[1] = argb[2];
|
|
saved[2] = argb[1];
|
|
saved[3] = argb[0];
|
|
}
|
|
unsigned char* const target = reinterpret_cast<unsigned char*>(&this->render.targetTintColor);
|
|
target[0] = 0xFF;
|
|
target[1] = static_cast<unsigned char>(b);
|
|
target[2] = static_cast<unsigned char>(c);
|
|
target[3] = static_cast<unsigned char>(d);
|
|
const std::int64_t red = b;
|
|
const std::int64_t green = c;
|
|
this->render.color = static_cast<std::uint32_t>(red << 16 | green << 8 | static_cast<std::uint32_t>(d) | 0xFF000000);
|
|
break;
|
|
}
|
|
case AM_RETURN_COLOR:
|
|
this->render.savedTintColor = 0;
|
|
this->render.colorLocked = 0;
|
|
break;
|
|
case AM_DELETE_BUYING_SHOP_TITLE:
|
|
if (this->actorWindows[4] == 0) {
|
|
break;
|
|
}
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->actorWindows[4]));
|
|
this->actorWindows[4] = 0;
|
|
break;
|
|
case AM_MAKE_BUYING_SHOP_TITLE: {
|
|
if (this->actorWindows[4] == 0) {
|
|
UIMerchantShopTitle* const title = new UIMerchantShopTitle(1);
|
|
this->actorWindows[4] = reinterpret_cast<int>(title);
|
|
title->SetSize(140, 34);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->actorWindows[4]));
|
|
}
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[4])->SendMsg(nullptr, UM_SETINFO, b, static_cast<std::int16_t>(this->render.fontSequenceState), 0, 0);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[4])->SendMsg(nullptr, UM_SETNAID, this->render.accountId, 0, 0, 0);
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[4])->Move(this->render.screenX - 70, this->render.screenY - ScaleByScreenHeight(110));
|
|
if (g_serviceOptions.Get(0xFA)) {
|
|
break;
|
|
}
|
|
reinterpret_cast<UIWindow*>(this->actorWindows[4])->Show(0);
|
|
break;
|
|
}
|
|
case AM_FALLEN_ANGEL:
|
|
if (g_session.IsPlayerJobId(this->GetEffectiveJob(-1))) {
|
|
if (CRagEffect* effect = this->LaunchEffect(0xA6, vector3d{0.0f, 0.0f, 0.0f}, 0.0f)) {
|
|
effect->SendMsg(nullptr, AM_SETCOUNT, 0, 0xFFFF, 0xF3, 0, 100, 0);
|
|
}
|
|
if (CEffect* fallenAngel = g_effectMgr->Find(this->render.accountId, 0x474)) {
|
|
vector3d position{0.0f, 0.0f, 0.0f};
|
|
static_cast<CGameMode*>(g_modeMgr.GetGameMode())->CellCenter(static_cast<int>(b), static_cast<int>(c), position.x, position.z);
|
|
position.y = this->render.position.y;
|
|
static_cast<CFallenAngelEffect*>(fallenAngel)->SetPosition(position);
|
|
}
|
|
}
|
|
this->SendMsg(nullptr, AM_STOPMOVE, b, d, 15, 0, 0, 0);
|
|
this->SetAction(this->render.animation, 6, 1);
|
|
this->render.curMotion = 7;
|
|
this->render.isMotionFreezed = true;
|
|
break;
|
|
case AM_UPDATE_MONSTER_GAGE:
|
|
if (b == -1 ||
|
|
c == -1) {
|
|
if (this->hpGaugeWindow == 0) {
|
|
break;
|
|
}
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->hpGaugeWindow));
|
|
this->hpGaugeWindow = 0;
|
|
break;
|
|
}
|
|
if (d == 1 && this->hpGaugeWindow != 0) {
|
|
g_windowMgr.Schedule(reinterpret_cast<UIWindow*>(this->hpGaugeWindow));
|
|
this->hpGaugeWindow = 0;
|
|
}
|
|
if (this->hpGaugeWindow == 0) {
|
|
UIMonsterGage* const gage = new UIMonsterGage();
|
|
this->hpGaugeWindow = reinterpret_cast<int>(gage);
|
|
gage->SetSize(60, 5);
|
|
g_windowMgr.AddRenderedFront(reinterpret_cast<UIWindow*>(this->hpGaugeWindow));
|
|
}
|
|
reinterpret_cast<UIPcGage*>(this->hpGaugeWindow)->SetValues(static_cast<int>(b), static_cast<int>(c));
|
|
reinterpret_cast<UIPcGage*>(this->hpGaugeWindow)->Move(
|
|
this->render.screenX - reinterpret_cast<UIPcGage*>(this->hpGaugeWindow)->geometry.width / 2,
|
|
static_cast<int>(static_cast<float>(ScaleByScreenHeight(12)) * this->render.distanceScale + static_cast<float>(this->render.screenY))
|
|
);
|
|
break;
|
|
case AM_MAKE_MISFORTUNE_EFFECT:
|
|
if (this->firstFollowerEffect == 0) {
|
|
CGameObject* effect = mode->SpawnMsgEffect(68, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->firstFollowerEffect = reinterpret_cast<int>(effect);
|
|
}
|
|
break;
|
|
case AM_DELETE_MISFORTUNE_EFFECT:
|
|
if (this->firstFollowerEffect != 0) {
|
|
reinterpret_cast<CGameObject*>(this->firstFollowerEffect)->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->firstFollowerEffect = 0;
|
|
}
|
|
break;
|
|
case AM_MAKE_DEEPSILENCE_EFFECT:
|
|
if (this->secondFollowerEffect == 0) {
|
|
CGameObject* effect = mode->SpawnMsgEffect(9, &this->render.position, this->render.accountId, true);
|
|
this->msgEffectList.push_back(effect);
|
|
effect->SendMsg(this, AM_SET_MASTER_POINTER, 0, 0, 0, 0, 0, 0);
|
|
this->secondFollowerEffect = reinterpret_cast<int>(effect);
|
|
}
|
|
break;
|
|
case AM_DELETE_DEEPSILENCE_EFFECT:
|
|
if (this->secondFollowerEffect != 0) {
|
|
reinterpret_cast<CGameObject*>(this->secondFollowerEffect)->SendMsg(nullptr, AM_DISAPPEAR, 0, 0, 0, 0, 0, 0);
|
|
this->secondFollowerEffect = 0;
|
|
}
|
|
break;
|
|
default:
|
|
this->EffectActor::SendMsg(sender, message, b, c, d, e, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
|