mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-26 15:33:34 +00:00
Merge branch 'property-fixes' of https://github.com/EmosewaMC/DarkflameServer into property-fixes
This commit is contained in:
commit
f72c2dcaa5
@ -6,6 +6,7 @@
|
||||
|
||||
#include "Database.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "User.h"
|
||||
#include <WorldPackets.h>
|
||||
#include "Character.h"
|
||||
@ -68,16 +69,6 @@ void UserManager::Initialize() {
|
||||
StripCR(line);
|
||||
m_PreapprovedNames.push_back(line);
|
||||
}
|
||||
|
||||
//Load custom ones from MySQL too:
|
||||
/*sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT name FROM approvedNames;");
|
||||
sql::ResultSet* res = stmt->executeQuery();
|
||||
while (res->next()) {
|
||||
m_PreapprovedNames.push_back(res->getString(1));
|
||||
}
|
||||
|
||||
delete res;
|
||||
delete stmt;*/
|
||||
}
|
||||
|
||||
UserManager::~UserManager() {
|
||||
@ -566,122 +557,38 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetShirtColorId(uint32_t color) {
|
||||
|
||||
// get the index of the color in shirtColorVector
|
||||
auto colorId = std::find(shirtColorVector.begin(), shirtColorVector.end(), color);
|
||||
return color = std::distance(shirtColorVector.begin(), colorId);
|
||||
}
|
||||
|
||||
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
||||
|
||||
shirtStyle--; // to start at 0 instead of 1
|
||||
uint32_t stylesCount = 34;
|
||||
uint32_t colorId = GetShirtColorId(shirtColor);
|
||||
|
||||
uint32_t startID = 4049; // item ID of the shirt with color 0 (red) and style 0 (plain)
|
||||
|
||||
// For some reason, if the shirt style is 34 - 39,
|
||||
// The ID is different than the original... Was this because
|
||||
// these shirts were added later?
|
||||
if (shirtStyle >= 34) {
|
||||
startID = 5730; // item ID of the shirt with color 0 (red) and style 34 (butterflies)
|
||||
shirtStyle -= stylesCount; //change style from range 35-40 to range 0-5
|
||||
stylesCount = 6;
|
||||
try {
|
||||
std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"character create shirt\" AND icc.color1 == ";
|
||||
shirtQuery += std::to_string(shirtColor);
|
||||
shirtQuery += " AND icc.decal == ";
|
||||
shirtQuery = shirtQuery + std::to_string(shirtStyle);
|
||||
auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery);
|
||||
auto shirtLOT = tableData.getIntField(0, -1);
|
||||
tableData.finalize();
|
||||
return shirtLOT;
|
||||
}
|
||||
catch (const std::exception&){
|
||||
Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
|
||||
// in case of no shirt found in CDServer, return problematic red vest.
|
||||
return 4069;
|
||||
}
|
||||
|
||||
// Get the final ID of the shirt
|
||||
uint32_t shirtID = startID + (colorId * stylesCount) + shirtStyle;
|
||||
|
||||
return shirtID;
|
||||
}
|
||||
|
||||
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
||||
uint32_t pantsID = 2508;
|
||||
|
||||
switch (pantsColor) {
|
||||
case 0: {
|
||||
pantsID = PANTS_BRIGHT_RED;
|
||||
break;
|
||||
try {
|
||||
std::string pantsQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == ";
|
||||
pantsQuery += std::to_string(pantsColor);
|
||||
auto tableData = CDClientDatabase::ExecuteQuery(pantsQuery);
|
||||
auto pantsLOT = tableData.getIntField(0, -1);
|
||||
tableData.finalize();
|
||||
return pantsLOT;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
pantsID = PANTS_BRIGHT_BLUE;
|
||||
break;
|
||||
catch (const std::exception&){
|
||||
Game::logger->Log("Character Create", "Failed to execute query! Using backup...");
|
||||
// in case of no pants color found in CDServer, return red pants.
|
||||
return 2508;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
pantsID = PANTS_DARK_GREEN;
|
||||
break;
|
||||
}
|
||||
|
||||
case 5: {
|
||||
pantsID = PANTS_BRIGHT_ORANGE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 6: {
|
||||
pantsID = PANTS_BLACK;
|
||||
break;
|
||||
}
|
||||
|
||||
case 7: {
|
||||
pantsID = PANTS_DARK_STONE_GRAY;
|
||||
break;
|
||||
}
|
||||
|
||||
case 8: {
|
||||
pantsID = PANTS_MEDIUM_STONE_GRAY;
|
||||
break;
|
||||
}
|
||||
|
||||
case 9: {
|
||||
pantsID = PANTS_REDDISH_BROWN;
|
||||
break;
|
||||
}
|
||||
|
||||
case 10: {
|
||||
pantsID = PANTS_WHITE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 11: {
|
||||
pantsID = PANTS_MEDIUM_BLUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 13: {
|
||||
pantsID = PANTS_DARK_RED;
|
||||
break;
|
||||
}
|
||||
|
||||
case 14: {
|
||||
pantsID = PANTS_EARTH_BLUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 15: {
|
||||
pantsID = PANTS_EARTH_GREEN;
|
||||
break;
|
||||
}
|
||||
|
||||
case 16: {
|
||||
pantsID = PANTS_BRICK_YELLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
case 84: {
|
||||
pantsID = PANTS_SAND_BLUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 96: {
|
||||
pantsID = PANTS_SAND_GREEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pantsID;
|
||||
}
|
||||
|
||||
void UserManager::SaveAllActiveCharacters() {
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
|
||||
private:
|
||||
static UserManager* m_Address; //Singleton
|
||||
//std::vector<User*> m_Users;
|
||||
std::map<SystemAddress, User*> m_Users;
|
||||
std::vector<User*> m_UsersToDelete;
|
||||
|
||||
@ -54,43 +53,4 @@ private:
|
||||
std::vector<std::string> m_PreapprovedNames;
|
||||
};
|
||||
|
||||
enum CharCreatePantsColor : uint32_t {
|
||||
PANTS_BRIGHT_RED = 2508,
|
||||
PANTS_BRIGHT_ORANGE = 2509,
|
||||
PANTS_BRICK_YELLOW = 2511,
|
||||
PANTS_MEDIUM_BLUE = 2513,
|
||||
PANTS_SAND_GREEN = 2514,
|
||||
PANTS_DARK_GREEN = 2515,
|
||||
PANTS_EARTH_GREEN = 2516,
|
||||
PANTS_EARTH_BLUE = 2517,
|
||||
PANTS_BRIGHT_BLUE = 2519,
|
||||
PANTS_SAND_BLUE = 2520,
|
||||
PANTS_DARK_STONE_GRAY = 2521,
|
||||
PANTS_MEDIUM_STONE_GRAY = 2522,
|
||||
PANTS_WHITE = 2523,
|
||||
PANTS_BLACK = 2524,
|
||||
PANTS_REDDISH_BROWN = 2526,
|
||||
PANTS_DARK_RED = 2527
|
||||
};
|
||||
|
||||
const std::vector<uint32_t> shirtColorVector {
|
||||
0, // BRIGHT_RED
|
||||
1, // BRIGHT_BLUE
|
||||
2, // BRIGHT_YELLOW
|
||||
3, // DARK_GREEN
|
||||
5, // BRIGHT_ORANGE
|
||||
6, // BLACK
|
||||
7, // DARK_STONE_GRAY
|
||||
8, // MEDIUM_STONE_GRAY
|
||||
9, // REDDISH_BROWN
|
||||
10, // WHITE
|
||||
11, // MEDIUM_BLUE
|
||||
13, // DARK_RED
|
||||
14, // EARTH_BLUE
|
||||
15, // EARTH_GREEN
|
||||
16, // BRICK_YELLOW
|
||||
84, // SAND_BLUE
|
||||
96 // SAND_GREEN
|
||||
};
|
||||
|
||||
#endif // USERMANAGER_H
|
||||
|
@ -1043,7 +1043,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks)
|
||||
|
||||
UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() });
|
||||
|
||||
if (item->GetParent() == LWOOBJID_EMPTY) ApplyBuff(item->GetLot());
|
||||
ApplyBuff(item);
|
||||
|
||||
AddItemSkills(item->GetLot());
|
||||
|
||||
@ -1071,7 +1071,7 @@ void InventoryComponent::UnEquipItem(Item* item)
|
||||
set->OnUnEquip(lot);
|
||||
}
|
||||
|
||||
if (item->GetParent() == LWOOBJID_EMPTY) RemoveBuff(item->GetLot());
|
||||
RemoveBuff(item);
|
||||
|
||||
RemoveItemSkills(item->GetLot());
|
||||
|
||||
@ -1089,9 +1089,9 @@ void InventoryComponent::UnEquipItem(Item* item)
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::ApplyBuff(const LOT lot) const
|
||||
void InventoryComponent::ApplyBuff(Item* item) const
|
||||
{
|
||||
const auto buffs = FindBuffs(lot, true);
|
||||
const auto buffs = FindBuffs(item, true);
|
||||
|
||||
for (const auto buff : buffs)
|
||||
{
|
||||
@ -1099,9 +1099,9 @@ void InventoryComponent::ApplyBuff(const LOT lot) const
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::RemoveBuff(const LOT lot) const
|
||||
void InventoryComponent::RemoveBuff(Item* item) const
|
||||
{
|
||||
const auto buffs = FindBuffs(lot, false);
|
||||
const auto buffs = FindBuffs(item, false);
|
||||
|
||||
for (const auto buff : buffs)
|
||||
{
|
||||
@ -1418,18 +1418,18 @@ uint32_t InventoryComponent::FindSkill(const LOT lot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> InventoryComponent::FindBuffs(const LOT lot, bool castOnEquip) const
|
||||
std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip) const
|
||||
{
|
||||
std::vector<uint32_t> buffs;
|
||||
if (item == nullptr) return buffs;
|
||||
auto* table = CDClientManager::Instance()->GetTable<CDObjectSkillsTable>("ObjectSkills");
|
||||
auto* behaviors = CDClientManager::Instance()->GetTable<CDSkillBehaviorTable>("SkillBehavior");
|
||||
|
||||
const auto results = table->Query([=](const CDObjectSkills& entry)
|
||||
{
|
||||
return entry.objectTemplate == static_cast<unsigned int>(lot);
|
||||
return entry.objectTemplate == static_cast<unsigned int>(item->GetLot());
|
||||
});
|
||||
|
||||
std::vector<uint32_t> buffs;
|
||||
|
||||
auto* missions = static_cast<MissionComponent*>(m_Parent->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
|
||||
for (const auto& result : results)
|
||||
@ -1449,8 +1449,8 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(const LOT lot, bool castOnEq
|
||||
{
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID);
|
||||
}
|
||||
|
||||
buffs.push_back(static_cast<uint32_t>(entry.behaviorID));
|
||||
// If item is not a proxy, add its buff to the added buffs.
|
||||
if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast<uint32_t>(entry.behaviorID));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1531,7 +1531,7 @@ std::vector<Item*> InventoryComponent::GenerateProxies(Item* parent)
|
||||
|
||||
auto* inventory = GetInventory(ITEM_SETS);
|
||||
|
||||
auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false, parent->GetId());
|
||||
auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false);
|
||||
|
||||
EquipItem(proxy);
|
||||
|
||||
|
@ -193,15 +193,15 @@ public:
|
||||
|
||||
/**
|
||||
* Adds a buff related to equipping a lot to the entity
|
||||
* @param lot the lot to find buffs for
|
||||
* @param item the item to find buffs for
|
||||
*/
|
||||
void ApplyBuff(LOT lot) const;
|
||||
void ApplyBuff(Item* item) const;
|
||||
|
||||
/**
|
||||
* Removes buffs related to equipping a lot from the entity
|
||||
* @param lot the lot to find buffs for
|
||||
* @param item the item to find buffs for
|
||||
*/
|
||||
void RemoveBuff(LOT lot) const;
|
||||
void RemoveBuff(Item* item) const;
|
||||
|
||||
/**
|
||||
* Saves the equipped items into a temp state
|
||||
@ -240,11 +240,11 @@ public:
|
||||
|
||||
/**
|
||||
* Finds all the buffs related to a lot
|
||||
* @param lot the lot to get the buffs for
|
||||
* @param item the item to get the buffs for
|
||||
* @param castOnEquip if true, the skill missions for these buffs will be progressed
|
||||
* @return the buffs related to the specified lot
|
||||
*/
|
||||
std::vector<uint32_t> FindBuffs(LOT lot, bool castOnEquip) const;
|
||||
std::vector<uint32_t> FindBuffs(Item* item, bool castOnEquip) const;
|
||||
|
||||
/**
|
||||
* Initializes the equipped items with a list of items
|
||||
|
@ -416,6 +416,7 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string&
|
||||
|
||||
case MissionTaskType::MISSION_TASK_TYPE_RACING:
|
||||
{
|
||||
// The meaning of associate can be found in RacingTaskParam.h
|
||||
if (parameters.empty()) break;
|
||||
|
||||
if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID()) && !(parameters[0] == 4 || parameters[0] == 5) && !InAllTargets(value)) break;
|
||||
@ -440,6 +441,11 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string&
|
||||
if (!InAllTargets(value)) break;
|
||||
AddProgress(count);
|
||||
}
|
||||
else if (associate == 17)
|
||||
{
|
||||
if (!InAllTargets(value)) break;
|
||||
AddProgress(count);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddProgress(count);
|
||||
|
@ -16,5 +16,5 @@ enum class RacingTaskParam : int32_t {
|
||||
RACING_TASK_PARAM_WIN_RACE_IN_WORLD = 14, //<! A task param for winning a race in a specific world.
|
||||
RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS = 15, //<! A task param for finishing in first place on multiple tracks.
|
||||
RACING_TASK_PARAM_LAST_PLACE_FINISH = 16, //<! A task param for finishing in last place.
|
||||
RACING_TASK_PARAM_SMASH_DRAGON_EGGS = 17 //<! A task param for smashing dragon eggs during a race.
|
||||
RACING_TASK_PARAM_SMASH_SPECIFIC_SMASHABLE = 17 //<! A task param for smashing dragon eggs during a race.
|
||||
};
|
@ -363,11 +363,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
}
|
||||
|
||||
if (user->GetMaxGMLevel() == 0 || entity->GetGMLevel() >= 0) {
|
||||
if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1) {
|
||||
std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size());
|
||||
GameMessages::SendPlayAnimation(entity, anim);
|
||||
}
|
||||
|
||||
if (chatCommand == "die") {
|
||||
entity->Smash(entity->GetObjectID());
|
||||
}
|
||||
@ -446,6 +441,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
|
||||
GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); // need to retoggle because it gets reenabled on creation of new character
|
||||
}
|
||||
|
||||
if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
||||
std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size());
|
||||
GameMessages::SendPlayAnimation(entity, anim);
|
||||
}
|
||||
|
||||
if (chatCommand == "list-spawns" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
||||
for (const auto& pair : EntityManager::Instance()->GetSpawnPointEntities()) {
|
||||
|
@ -1,15 +1,66 @@
|
||||
#include "AgSurvivalBuffStation.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "dLogger.h"
|
||||
#include "TeamManager.h"
|
||||
|
||||
void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
auto destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
// We set the faction to 6 so that the buff station sees players as friendly targets to buff
|
||||
if (destroyableComponent != nullptr) destroyableComponent->SetFaction(6);
|
||||
|
||||
auto skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) return;
|
||||
if (skillComponent != nullptr) skillComponent->CalculateBehavior(skillIdForBuffStation, behaviorIdForBuffStation, self->GetObjectID());
|
||||
|
||||
skillComponent->CalculateBehavior(201, 1784, self->GetObjectID());
|
||||
|
||||
self->AddCallbackTimer(10.0f, [self]() {
|
||||
self->AddCallbackTimer(smashTimer, [self]() {
|
||||
self->Smash();
|
||||
});
|
||||
self->AddTimer("DropArmor", dropArmorTimer);
|
||||
self->AddTimer("DropLife", dropLifeTimer);
|
||||
self->AddTimer("Dropimagination", dropImaginationTimer);
|
||||
// Since all survival players should be on the same team, we get the team.
|
||||
auto team = TeamManager::Instance()->GetTeam(target->GetObjectID());
|
||||
|
||||
std::vector<LWOOBJID> builderTeam;
|
||||
// Not on a team
|
||||
if (team == nullptr) {
|
||||
builderTeam.push_back(target->GetObjectID());
|
||||
self->SetVar<std::vector<LWOOBJID>>(u"BuilderTeam", builderTeam);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto memberID : team->members) {
|
||||
builderTeam.push_back(memberID);
|
||||
}
|
||||
self->SetVar<std::vector<LWOOBJID>>(u"BuilderTeam", builderTeam);
|
||||
}
|
||||
|
||||
void AgSurvivalBuffStation::OnTimerDone(Entity* self, std::string timerName) {
|
||||
uint32_t powerupToDrop = lifePowerup;
|
||||
if (timerName == "DropArmor") {
|
||||
powerupToDrop = armorPowerup;
|
||||
self->AddTimer("DropArmor", dropArmorTimer);
|
||||
}
|
||||
if (timerName == "DropLife") {
|
||||
powerupToDrop = lifePowerup;
|
||||
self->AddTimer("DropLife", dropLifeTimer);
|
||||
}
|
||||
if (timerName == "Dropimagination") {
|
||||
powerupToDrop = imaginationPowerup;
|
||||
self->AddTimer("Dropimagination", dropImaginationTimer);
|
||||
}
|
||||
auto team = self->GetVar<std::vector<LWOOBJID>>(u"BuilderTeam");
|
||||
for (auto memberID : team) {
|
||||
auto member = EntityManager::Instance()->GetEntity(memberID);
|
||||
if (member != nullptr && !member->GetIsDead()) {
|
||||
GameMessages::SendDropClientLoot(member, self->GetObjectID(), powerupToDrop, 0, self->GetPosition());
|
||||
} else {
|
||||
// If player left the team or left early erase them from the team variable.
|
||||
team.erase(std::find(team.begin(), team.end(), memberID));
|
||||
self->SetVar<std::vector<LWOOBJID>>(u"BuilderTeam", team);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ public:
|
||||
* @param target The target of the self that called this script.
|
||||
*/
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
private:
|
||||
/**
|
||||
* Skill ID for the buff station.
|
||||
@ -20,4 +21,32 @@ private:
|
||||
* Behavior ID for the buff station.
|
||||
*/
|
||||
uint32_t behaviorIdForBuffStation = 1784;
|
||||
/**
|
||||
* Timer for dropping armor.
|
||||
*/
|
||||
float dropArmorTimer = 6.0f;
|
||||
/**
|
||||
* Timer for dropping life.
|
||||
*/
|
||||
float dropLifeTimer = 3.0f;
|
||||
/**
|
||||
* Timer for dropping imagination.
|
||||
*/
|
||||
float dropImaginationTimer = 4.0f;
|
||||
/**
|
||||
* Timer for smashing.
|
||||
*/
|
||||
float smashTimer = 25.0f;
|
||||
/**
|
||||
* LOT for armor powerup.
|
||||
*/
|
||||
LOT armorPowerup = 6431;
|
||||
/**
|
||||
* LOT for life powerup.
|
||||
*/
|
||||
LOT lifePowerup = 177;
|
||||
/**
|
||||
* LOT for imagination powerup.
|
||||
*/
|
||||
LOT imaginationPowerup = 935;
|
||||
};
|
164
dScripts/AmDarklingDragon.cpp
Normal file
164
dScripts/AmDarklingDragon.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include "AmDarklingDragon.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
|
||||
void AmDarklingDragon::OnStartup(Entity* self) {
|
||||
self->SetVar<int32_t>(u"weakspot", 0);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnDie(Entity* self, Entity* killer) {
|
||||
if (self->GetVar<bool>(u"bDied")) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->SetVar<bool>(u"bDied", true);
|
||||
|
||||
auto golemId = self->GetVar<LWOOBJID>(u"Golem");
|
||||
|
||||
auto* golem = EntityManager::Instance()->GetEntity(golemId);
|
||||
|
||||
if (golem != nullptr) {
|
||||
golem->Smash(self->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true);
|
||||
|
||||
if (true) {
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakspot");
|
||||
|
||||
if (weakpoint == 1)
|
||||
{
|
||||
self->Smash(attacker->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr) {
|
||||
Game::logger->Log("AmDarklingDragon", "Armor is %i\n", destroyableComponent->GetArmor());
|
||||
|
||||
if (destroyableComponent->GetArmor() > 0) return;
|
||||
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakpoint");
|
||||
|
||||
if (weakpoint == 0) {
|
||||
Game::logger->Log("AmDarklingDragon", "Activating weakpoint\n");
|
||||
|
||||
self->AddTimer("ReviveTimer", 12);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetDisabled(true);
|
||||
baseCombatAIComponent->SetStunned(true);
|
||||
}
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakpoint", 2);
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f);
|
||||
|
||||
self->AddTimer("timeToStunLoop", 1);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto backwards = forward * -1;
|
||||
|
||||
forward.x *= 10;
|
||||
forward.z *= 10;
|
||||
|
||||
auto rotation = self->GetRotation();
|
||||
|
||||
auto objectPosition = NiPoint3();
|
||||
|
||||
objectPosition.y = position.y;
|
||||
objectPosition.x = position.x - (backwards.x * 8);
|
||||
objectPosition.z = position.z - (backwards.z * 8);
|
||||
|
||||
auto golem = self->GetVar<int32_t>(u"DragonSmashingGolem");
|
||||
|
||||
EntityInfo info {};
|
||||
info.lot = golem != 0 ? golem : 8340;
|
||||
info.pos = objectPosition;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = self->GetObjectID();
|
||||
info.settings = {
|
||||
new LDFData<std::string>(u"rebuild_activators",
|
||||
std::to_string(objectPosition.x + forward.x) + "\x1f" +
|
||||
std::to_string(objectPosition.y) + "\x1f" +
|
||||
std::to_string(objectPosition.z + forward.z)
|
||||
),
|
||||
new LDFData<int32_t>(u"respawn", 100000),
|
||||
new LDFData<float>(u"rebuild_reset_time", 15),
|
||||
new LDFData<bool>(u"no_timed_spawn", true),
|
||||
new LDFData<LWOOBJID>(u"Dragon", self->GetObjectID())
|
||||
};
|
||||
|
||||
auto* golemObject = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(golemObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "ReviveHeldTimer") {
|
||||
self->AddTimer("backToAttack", 2.5);
|
||||
}
|
||||
else if (timerName == "ExposeWeakSpotTimer") {
|
||||
self->SetVar<int32_t>(u"weakspot", 1);
|
||||
}
|
||||
else if (timerName == "timeToStunLoop") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f);
|
||||
}
|
||||
else if (timerName == "ReviveTimer") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunend", 2.0f);
|
||||
self->AddTimer("backToAttack", 1);
|
||||
}
|
||||
else if (timerName == "backToAttack") {
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (baseCombatAIComponent != nullptr)
|
||||
{
|
||||
baseCombatAIComponent->SetDisabled(false);
|
||||
baseCombatAIComponent->SetStunned(false);
|
||||
}
|
||||
if (skillComponent != nullptr)
|
||||
{
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
self->SetVar<int32_t>(u"weakspot", -1);
|
||||
GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
|
||||
if (args != "rebuildDone") return;
|
||||
|
||||
self->AddTimer("ExposeWeakSpotTimer", 3.8f);
|
||||
|
||||
self->CancelTimer("ReviveTimer");
|
||||
|
||||
self->AddTimer("ReviveHeldTimer", 10.5f);
|
||||
|
||||
self->SetVar<LWOOBJID>(u"Golem", sender->GetObjectID());
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f);
|
||||
}
|
48
dScripts/AmDarklingDragon.h
Normal file
48
dScripts/AmDarklingDragon.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmDarklingDragon : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief When called, this function will make self immune to stuns and initialize a weakspot boolean to false.
|
||||
*
|
||||
* @param self The Entity that called this function.
|
||||
*/
|
||||
void OnStartup(Entity* self) override;
|
||||
/**
|
||||
* @brief When called, this function will destroy the golem if it was alive, otherwise returns immediately.
|
||||
*
|
||||
* @param self The Entity that called this function.
|
||||
* @param killer The Entity that killed self.
|
||||
*/
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
/**
|
||||
* @brief When self is hit or healed, this function will check if self is at zero armor. If self is at zero armor, a golem Entity Quick Build
|
||||
* is spawned that, when built, will reveal a weakpoint on the dragon that if hit will smash the dragon instantly. If at more than zero armor,
|
||||
* this function returns early.
|
||||
*
|
||||
* @param self The Entity that was hit.
|
||||
* @param attacker The Entity that attacked self.
|
||||
* @param damage The amount of damage attacker did to self.
|
||||
*/
|
||||
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
/**
|
||||
* @brief Called when self has a timer that ended.
|
||||
*
|
||||
* @param self The Entity who owns a timer that finished.
|
||||
* @param timerName The name of a timer attacked to self that has ended.
|
||||
*/
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
/**
|
||||
* @brief When the Client has finished rebuilding the Golem for the dragon, this function exposes the weak spot for a set amount of time.
|
||||
*
|
||||
* @param self The Entity that called this script.
|
||||
* @param sender The Entity that sent a fired event.
|
||||
* @param args The argument that tells us what event has been fired off.
|
||||
* @param param1 Unused in this script.
|
||||
* @param param2 Unused in this script.
|
||||
* @param param3 Unused in this script.
|
||||
*/
|
||||
void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
#include "AmNamedDarklingDragon.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
void AmNamedDarklingDragon::OnStartup(Entity* self)
|
||||
{
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr)
|
||||
{
|
||||
baseCombatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmNamedDarklingDragon : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
@ -8,11 +8,6 @@
|
||||
void BaseEnemyApe::OnStartup(Entity *self) {
|
||||
self->SetVar<uint32_t>(u"timesStunned", 2);
|
||||
self->SetVar<bool>(u"knockedOut", false);
|
||||
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnDie(Entity *self, Entity *killer) {
|
||||
@ -23,10 +18,8 @@ void BaseEnemyApe::OnDie(Entity *self, Entity *killer) {
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnSkillCast(Entity *self, uint32_t skillID) {
|
||||
const auto groundPoundSkill = self->GetVar<uint32_t>(u"GroundPoundSkill") != 0
|
||||
? self->GetVar<uint32_t>(u"GroundPoundSkill") : 725;
|
||||
const auto spawnQuickBuildTime = self->GetVar<float_t>(u"spawnQBTime") != 0.0f
|
||||
? self->GetVar<float_t>(u"spawnQBTime") : 5.0f;
|
||||
const auto groundPoundSkill = self->GetVar<uint32_t>(u"GroundPoundSkill") != 0 ? self->GetVar<uint32_t>(u"GroundPoundSkill") : 725;
|
||||
const auto spawnQuickBuildTime = self->GetVar<float_t>(u"spawnQBTime") != 0.0f ? self->GetVar<float_t>(u"spawnQBTime") : 5.0f;
|
||||
|
||||
if (skillID == groundPoundSkill && self->GetVar<LWOOBJID>(u"QB") == LWOOBJID_EMPTY) {
|
||||
self->AddTimer("spawnQBTime", spawnQuickBuildTime);
|
||||
@ -61,9 +54,7 @@ void BaseEnemyApe::OnTimerDone(Entity *self, std::string timerName) {
|
||||
StunApe(self, false);
|
||||
|
||||
} else if (timerName == "spawnQBTime" && self->GetVar<LWOOBJID>(u"QB") == LWOOBJID_EMPTY) {
|
||||
|
||||
// Spawns the QB, which can insta kill the ape
|
||||
// Quick mafs to spawn the QB in the correct spot
|
||||
// Spawn QB in front of ape.
|
||||
const auto position = self->GetPosition();
|
||||
const auto rotation = self->GetRotation();
|
||||
|
||||
@ -107,8 +98,6 @@ void BaseEnemyApe::OnTimerDone(Entity *self, std::string timerName) {
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (skillComponent != nullptr) {
|
||||
// We use a different behavior than the script here, the original one contains a TargetCaster behavior
|
||||
// but as of writing we can't pass an optional originated to give the loot to the player
|
||||
skillComponent->CalculateBehavior(1273, 29446, self->GetObjectID(), true, false, player->GetObjectID());
|
||||
}
|
||||
|
||||
@ -120,8 +109,7 @@ void BaseEnemyApe::OnFireEventServerSide(Entity *self, Entity *sender, std::stri
|
||||
int32_t param3) {
|
||||
if (args == "rebuildDone" && sender != nullptr) {
|
||||
self->SetVar<LWOOBJID>(u"smasher", sender->GetObjectID());
|
||||
const auto anchorDamageDelayTime = self->GetVar<float_t>(u"AnchorDamageDelayTime") != 0.0f
|
||||
? self->GetVar<float_t>(u"AnchorDamageDelayTime") : 0.5f;
|
||||
const auto anchorDamageDelayTime = self->GetVar<float_t>(u"AnchorDamageDelayTime") != 0.0f ? self->GetVar<float_t>(u"AnchorDamageDelayTime") : 0.5f;
|
||||
self->AddTimer("anchorDamageTimer", anchorDamageDelayTime);
|
||||
}
|
||||
}
|
||||
|
@ -200,6 +200,7 @@ void BaseSurvivalServer::OnActivityTimerDone(Entity *self, const std::string &na
|
||||
ActivityTimerStop(self, SpawnTickTimer);
|
||||
ActivityTimerStart(self, CoolDownStopTimer, 1, constants.coolDownTime);
|
||||
|
||||
ActivateSpawnerNetwork(spawnerNetworks.rewardNetworks);
|
||||
SpawnerReset(spawnerNetworks.baseNetworks, false);
|
||||
SpawnerReset(spawnerNetworks.randomNetworks, false);
|
||||
} else if (name == CoolDownStopTimer) {
|
||||
@ -302,7 +303,6 @@ void BaseSurvivalServer::StartWaves(Entity *self) {
|
||||
self->SetVar<bool>(FirstTimeDoneVariable, true);
|
||||
self->SetVar<std::string>(MissionTypeVariable, state.players.size() == 1 ? "survival_time_solo" : "survival_time_team");
|
||||
|
||||
ActivateSpawnerNetwork(spawnerNetworks.rewardNetworks);
|
||||
ActivateSpawnerNetwork(spawnerNetworks.smashNetworks);
|
||||
self->SetNetworkVar<bool>(WavesStartedVariable, true);
|
||||
self->SetNetworkVar<std::string>(StartWaveMessageVariable, "Start!");
|
||||
|
@ -181,6 +181,7 @@
|
||||
#include "NtVentureCannonServer.h"
|
||||
#include "NtCombatChallengeServer.h"
|
||||
#include "NtCombatChallengeDummy.h"
|
||||
#include "NtCombatChallengeExplodingDummy.h"
|
||||
#include "BaseInteractDropLootServer.h"
|
||||
#include "NtAssemblyTubeServer.h"
|
||||
#include "NtParadoxPanelServer.h"
|
||||
@ -223,7 +224,7 @@
|
||||
#include "AmSkullkinDrill.h"
|
||||
#include "AmSkullkinDrillStand.h"
|
||||
#include "AmSkullkinTower.h"
|
||||
#include "AmNamedDarklingDragon.h"
|
||||
#include "AmDarklingDragon.h"
|
||||
#include "AmBlueX.h"
|
||||
|
||||
// NJ Scripts
|
||||
@ -615,6 +616,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
|
||||
script = new NtCombatChallengeServer();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua")
|
||||
script = new NtCombatChallengeDummy();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\NT\\\\L_NT_COMBAT_EXPLODING_TARGET.lua")
|
||||
script = new NtCombatChallengeExplodingDummy();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\General\\L_BASE_INTERACT_DROP_LOOT_SERVER.lua")
|
||||
script = new BaseInteractDropLootServer();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\NT\\L_NT_ASSEMBLYTUBE_SERVER.lua")
|
||||
@ -687,11 +690,10 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
|
||||
script = new AmSkullkinDrillStand();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua")
|
||||
script = new AmSkullkinTower();
|
||||
// This just makes them immune to stuns. TODO: Make seperate scripts
|
||||
else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_NAMED_DARKLING_DRAGON.lua")
|
||||
script = new AmNamedDarklingDragon();
|
||||
script = new AmDarklingDragon();
|
||||
else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_DRAGON.lua")
|
||||
script = new AmNamedDarklingDragon();
|
||||
script = new AmDarklingDragon();
|
||||
else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua")
|
||||
script = new BaseEnemyApe();
|
||||
else if (scriptName == "scripts\\02_server\\Map\\AM\\L_BLUE_X.lua")
|
||||
|
@ -27,7 +27,9 @@ void FvRaceSmashEggImagineServer::OnDie(Entity *self, Entity *killer) {
|
||||
characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed);
|
||||
}
|
||||
if (missionComponent == nullptr) return;
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_DRAGON_EGGS);
|
||||
// Dragon eggs have their own smash server so we handle mission progression for them here.
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES);
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_SPECIFIC_SMASHABLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
38
dScripts/NtCombatChallengeExplodingDummy.cpp
Normal file
38
dScripts/NtCombatChallengeExplodingDummy.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "NtCombatChallengeExplodingDummy.h"
|
||||
#include "NtCombatChallengeDummy.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer)
|
||||
{
|
||||
const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID");
|
||||
|
||||
auto* challengeObject = EntityManager::Instance()->GetEntity(challengeObjectID);
|
||||
|
||||
if (challengeObject != nullptr)
|
||||
{
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(challengeObject))
|
||||
{
|
||||
script->OnDie(challengeObject, killer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID");
|
||||
|
||||
auto* challengeObject = EntityManager::Instance()->GetEntity(challengeObjectID);
|
||||
|
||||
if (challengeObject != nullptr)
|
||||
{
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(challengeObject))
|
||||
{
|
||||
script->OnHitOrHealResult(challengeObject, attacker, damage);
|
||||
}
|
||||
}
|
||||
auto skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID());
|
||||
}
|
||||
self->Kill(attacker);
|
||||
}
|
8
dScripts/NtCombatChallengeExplodingDummy.h
Normal file
8
dScripts/NtCombatChallengeExplodingDummy.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NtCombatChallengeExplodingDummy : public CppScripts::Script
|
||||
{
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
};
|
@ -22,6 +22,8 @@ void RaceSmashServer::OnDie(Entity *self, Entity *killer) {
|
||||
// Progress racing smashable missions
|
||||
if(missionComponent == nullptr) return;
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES);
|
||||
// Progress missions that ask us to smash a specific smashable.
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_SPECIFIC_SMASHABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ void WaveBossApe::OnFireEventServerSide(Entity *self, Entity *sender, std::strin
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(false);
|
||||
combatAIComponent->SetStunImmune(false);
|
||||
}
|
||||
} else {
|
||||
BaseEnemyApe::OnFireEventServerSide(self, sender, args, param1, param2, param3);
|
||||
|
Loading…
Reference in New Issue
Block a user