Compare commits

...

9 Commits

Author SHA1 Message Date
David Markowitz
f0a72873f2 Update 9_Update_Leaderboard_Storage.sql 2024-03-29 17:24:59 -07:00
jadebenn
150031861d Update README.md (#1518) 2024-03-28 21:32:46 -05:00
jadebenn
9d8e0a9c4a unbreak the stacktraces (#1516) 2024-03-27 06:10:39 +01:00
David Markowitz
bd9b790e1d feat: Add MovingAI pathing for NPCs without combatAI (#1509)
* remove goto

* Update MovementAIComponent.cpp

* convert to PathWaypoint

Easier for usage with paths

* add path parsing

* ref removal, simplification of work

* it works

* Update MovementAIComponent.cpp

* disable pathing for combat

we just need it for npcs for now, combat ai can be done later

* fixed stuttery enemies

wow

* start at ramped up speed

* add pausing and resuming

* Update MovementAIComponent.cpp

* Update MovementAIComponent.h

* Update CMakeLists.txt
2024-03-26 21:06:22 -05:00
David Markowitz
39b81b6263 rename and shorted BehaviorTemplate enum (#1512)
just a renaming of the enum and the value names and deletion of the empty cpp file.  Code compiles still.
2024-03-26 06:35:35 -05:00
David Markowitz
1e09ec92e3 Update PlayerContainer.cpp (#1513)
Prevents a bad actor from possibly spamming the server with sequential IDs and allocating a bunch of memory.

Tested that I can still send and receive friend requests
2024-03-26 06:20:45 -05:00
David Markowitz
2b253a8248 fix: movement ai remove goto, do todo, remove unused call (#1505)
* remove goto

* Update MovementAIComponent.cpp
2024-03-24 22:24:38 -05:00
David Markowitz
3262bc3a86 chore: Remove news in Behavior members (#1504)
* Remove news in behavior members

Tested that GrowingFlowers still have their SkillEvent fired with the correct parameters, gftikitorch works, sharks eating stinky fish still work

* explicitly default move assignment and copy operators/constructors

---------

Co-authored-by: jadebenn <jadebenn@users.noreply.github.com>
2024-03-24 21:43:01 -05:00
David Markowitz
3a4e554da9 update switch behavior (#1503)
was using very old code from pre-foss that has not been updated with the new behavior knowledge.  The code has been updated accordingly to what the client expects.

Tested that ice shurikens can now destroy the legs of the skeleton towers in crux prime.  Tested that the following weapons can still do damage to enemies and objects in the world:
surikens of ice
serratorizer
Super Morning Star
Super Dagger
elite long barrel blaster (charge and normal)
Mosaic Wand
2024-03-24 14:01:12 -05:00
25 changed files with 414 additions and 337 deletions

View File

@@ -4,8 +4,9 @@ include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file

View File

@@ -73,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
```
#### Required CMake version
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed.
This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
You can check your CMake version by using the following command in a terminal.
```bash
cmake --version

View File

@@ -390,7 +390,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
return m_Players[playerID];
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {

View File

@@ -731,15 +731,21 @@ void Entity::Initialize() {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName);
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>();
if (movementAIcomp){
// TODO: set path in existing movementAIComp
} else if (path->pathType == PathType::Movement) {
auto movementAIcomponent = GetComponent<MovementAIComponent>();
if (movementAIcomponent && combatAiId == 0) {
movementAIcomponent->SetPath(pathName);
} else {
// TODO: create movementAIcomp and set path
MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = "";
moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
AddComponent<MovementAIComponent>(moveInfo);
}
}*/
}
} else {
// else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);

View File

@@ -222,7 +222,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
if (healthDamageDealt >= 1) {
successState = eBasicAttackSuccessTypes::SUCCESS;
} else if (armorDamageDealt >= 1) {
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
}
bitStream.Write(armorDamageDealt);

View File

@@ -5,7 +5,7 @@
#include "CDActivitiesTable.h"
#include "Game.h"
#include "Logger.h"
#include "BehaviorTemplates.h"
#include "BehaviorTemplate.h"
#include "BehaviorBranchContext.h"
#include <unordered_map>
@@ -110,176 +110,176 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
Behavior* behavior = nullptr;
switch (templateId) {
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
case BehaviorTemplate::EMPTY: break;
case BehaviorTemplate::BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
case BehaviorTemplate::TAC_ARC:
behavior = new TacArcBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AND:
case BehaviorTemplate::AND:
behavior = new AndBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
case BehaviorTemplate::PROJECTILE_ATTACK:
behavior = new ProjectileAttackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_HEAL:
case BehaviorTemplate::HEAL:
behavior = new HealBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
case BehaviorTemplate::MOVEMENT_SWITCH:
behavior = new MovementSwitchBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
case BehaviorTemplate::AREA_OF_EFFECT:
behavior = new AreaOfEffectBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
case BehaviorTemplate::PLAY_EFFECT:
behavior = new PlayEffectBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
case BehaviorTemplate::IMMUNITY:
behavior = new ImmunityBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
case BehaviorTemplate::DAMAGE_BUFF: break;
case BehaviorTemplate::DAMAGE_ABSORBTION:
behavior = new DamageAbsorptionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
case BehaviorTemplate::OVER_TIME:
behavior = new OverTimeBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
case BehaviorTemplate::IMAGINATION:
behavior = new ImaginationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
case BehaviorTemplate::TARGET_CASTER:
behavior = new TargetCasterBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_STUN:
case BehaviorTemplate::STUN:
behavior = new StunBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DURATION:
case BehaviorTemplate::DURATION:
behavior = new DurationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
case BehaviorTemplate::KNOCKBACK:
behavior = new KnockbackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
case BehaviorTemplate::ATTACK_DELAY:
behavior = new AttackDelayBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
case BehaviorTemplate::CAR_BOOST:
behavior = new CarBoostBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
case BehaviorTemplate::FALL_SPEED:
behavior = new FallSpeedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
case BehaviorTemplate::SHIELD: break;
case BehaviorTemplate::REPAIR_ARMOR:
behavior = new RepairBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPEED:
case BehaviorTemplate::SPEED:
behavior = new SpeedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
case BehaviorTemplate::DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
case BehaviorTemplate::LOOT_BUFF:
behavior = new LootBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION:
case BehaviorTemplate::VENTURE_VISION:
behavior = new VentureVisionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
case BehaviorTemplate::SPAWN_OBJECT:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
case BehaviorTemplates::BEHAVIOR_SWITCH:
case BehaviorTemplate::LAY_BRICK: break;
case BehaviorTemplate::SWITCH:
behavior = new SwitchBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_BUFF:
case BehaviorTemplate::BUFF:
behavior = new BuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_JETPACK:
case BehaviorTemplate::JETPACK:
behavior = new JetPackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
case BehaviorTemplate::SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM:
case BehaviorTemplate::CONSUME_ITEM:
behavior = new ConsumeItemBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
case BehaviorTemplate::SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS:
case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
case BehaviorTemplate::CHANGE_IDLE_FLAGS:
behavior = new ChangeIdleFlagsBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
case BehaviorTemplate::APPLY_BUFF:
behavior = new ApplyBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CHAIN:
case BehaviorTemplate::CHAIN:
behavior = new ChainBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
case BehaviorTemplate::CHANGE_ORIENTATION:
behavior = new ChangeOrientationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
case BehaviorTemplate::FORCE_MOVEMENT:
behavior = new ForceMovementBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
case BehaviorTemplate::INTERRUPT:
behavior = new InterruptBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
case BehaviorTemplate::ALTER_COOLDOWN: break;
case BehaviorTemplate::CHARGE_UP:
behavior = new ChargeUpBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
case BehaviorTemplate::SWITCH_MULTIPLE:
behavior = new SwitchMultipleBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_START:
case BehaviorTemplate::START:
behavior = new StartBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_END:
case BehaviorTemplate::END:
behavior = new EndBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF:
case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
case BehaviorTemplate::CAMERA: break;
case BehaviorTemplate::REMOVE_BUFF:
behavior = new RemoveBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_GRAB: break;
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
case BehaviorTemplate::GRAB: break;
case BehaviorTemplate::MODULAR_BUILD: break;
case BehaviorTemplate::NPC_COMBAT_SKILL:
behavior = new NpcCombatSkillBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_BLOCK:
case BehaviorTemplate::BLOCK:
behavior = new BlockBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_VERIFY:
case BehaviorTemplate::VERIFY:
behavior = new VerifyBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAUNT:
case BehaviorTemplate::TAUNT:
behavior = new TauntBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
case BehaviorTemplate::AIR_MOVEMENT:
behavior = new AirMovementBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
case BehaviorTemplate::SPAWN_QUICKBUILD:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
case BehaviorTemplate::PULL_TO_POINT:
behavior = new PullToPointBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
case BehaviorTemplate::PROPERTY_ROTATE: break;
case BehaviorTemplate::DAMAGE_REDUCTION:
behavior = new DamageReductionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT:
case BehaviorTemplate::PROPERTY_TELEPORT:
behavior = new PropertyTeleportBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
behavior = new ClearTargetBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
case BehaviorTemplate::TAKE_PICTURE: break;
case BehaviorTemplate::MOUNT: break;
case BehaviorTemplate::SKILL_SET: break;
default:
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
break;
@@ -296,19 +296,19 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
return behavior;
}
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY;
BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
// Find behavior template by its behavior id. Default to 0.
if (behaviorTemplateTable) {
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
if (templateEntry.behaviorID == behaviorId) {
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID);
templateID = static_cast<BehaviorTemplate>(templateEntry.templateID);
}
}
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
LOG("Failed to load behavior template with id (%i)!", behaviorId);
}
@@ -335,26 +335,22 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
if (m_effectNames == nullptr) {
m_effectNames = new std::unordered_map<std::string, std::string>();
} else {
const auto pair = m_effectNames->find(typeString);
const auto itr = m_effectNames.find(typeString);
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
}
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(m_effectType);
}
if (pair != m_effectNames->end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
return;
}
renderComponent->PlayEffect(effectId, type, pair->second, secondary);
if (itr != m_effectNames.end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true);
return;
}
renderComponent->PlayEffect(effectId, type, itr->second, secondary);
return;
}
// The SQlite result object becomes invalid if the query object leaves scope.
@@ -388,12 +384,12 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
type = GeneralUtils::ASCIIToUTF16(typeResult);
m_effectType = new std::string(typeResult);
m_effectType = typeResult;
}
result.finalize();
m_effectNames->insert_or_assign(typeString, name);
m_effectNames.insert_or_assign(typeString, name);
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
@@ -423,8 +419,7 @@ Behavior::Behavior(const uint32_t behaviorId) {
if (behaviorId == 0) {
this->m_effectId = 0;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
this->m_templateId = BehaviorTemplate::EMPTY;
}
// Make sure we do not proceed if we are trying to load an invalid behavior
@@ -432,17 +427,16 @@ Behavior::Behavior(const uint32_t behaviorId) {
LOG("Failed to load behavior with id (%i)!", behaviorId);
this->m_effectId = 0;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
this->m_templateId = BehaviorTemplate::EMPTY;
return;
}
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID);
this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
this->m_effectId = templateInDatabase.effectID;
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
this->m_effectHandle = *templateInDatabase.effectHandle;
}
@@ -507,9 +501,3 @@ void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream,
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
}
Behavior::~Behavior() {
delete m_effectNames;
delete m_effectType;
delete m_effectHandle;
}

View File

@@ -6,7 +6,7 @@
#include <unordered_map>
#include "BitStream.h"
#include "BehaviorTemplates.h"
#include "BehaviorTemplate.h"
#include "dCommonVars.h"
struct BehaviorContext;
@@ -26,7 +26,7 @@ public:
static Behavior* CreateBehavior(uint32_t behaviorId);
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
/*
* Utilities
@@ -39,11 +39,11 @@ public:
*/
uint32_t m_behaviorId;
BehaviorTemplates m_templateId;
BehaviorTemplate m_templateId;
uint32_t m_effectId;
std::string* m_effectHandle = nullptr;
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
std::string* m_effectType = nullptr;
std::string m_effectHandle;
std::unordered_map<std::string, std::string> m_effectNames;
std::string m_effectType;
/*
* Behavior parameters
@@ -88,5 +88,11 @@ public:
*/
explicit Behavior(uint32_t behaviorId);
virtual ~Behavior();
virtual ~Behavior() = default;
Behavior(const Behavior& other) = default;
Behavior(Behavior&& other) = default;
Behavior& operator=(const Behavior& other) = default;
Behavior& operator=(Behavior&& other) = default;
};

View File

@@ -0,0 +1,70 @@
#pragma once
enum class BehaviorTemplate : unsigned int {
EMPTY, // Not a real behavior, indicates invalid behaviors
BASIC_ATTACK,
TAC_ARC,
AND,
PROJECTILE_ATTACK,
HEAL,
MOVEMENT_SWITCH,
AREA_OF_EFFECT,
PLAY_EFFECT,
IMMUNITY,
DAMAGE_BUFF,
DAMAGE_ABSORBTION,
OVER_TIME,
IMAGINATION,
TARGET_CASTER,
STUN,
DURATION,
KNOCKBACK,
ATTACK_DELAY,
CAR_BOOST,
FALL_SPEED,
SHIELD,
REPAIR_ARMOR,
SPEED,
DARK_INSPIRATION,
LOOT_BUFF,
VENTURE_VISION,
SPAWN_OBJECT,
LAY_BRICK,
SWITCH,
BUFF,
JETPACK,
SKILL_EVENT,
CONSUME_ITEM,
SKILL_CAST_FAILED,
IMITATION_SKUNK_STINK,
CHANGE_IDLE_FLAGS,
APPLY_BUFF,
CHAIN,
CHANGE_ORIENTATION,
FORCE_MOVEMENT,
INTERRUPT,
ALTER_COOLDOWN,
CHARGE_UP,
SWITCH_MULTIPLE,
START,
END,
ALTER_CHAIN_DELAY,
CAMERA,
REMOVE_BUFF,
GRAB,
MODULAR_BUILD,
NPC_COMBAT_SKILL,
BLOCK,
VERIFY,
TAUNT,
AIR_MOVEMENT,
SPAWN_QUICKBUILD,
PULL_TO_POINT,
PROPERTY_ROTATE,
DAMAGE_REDUCTION,
PROPERTY_TELEPORT,
PROPERTY_CLEAR_TARGET,
TAKE_PICTURE,
MOUNT,
SKILL_SET
};

View File

@@ -1 +0,0 @@
#include "BehaviorTemplates.h"

View File

@@ -1,70 +0,0 @@
#pragma once
enum class BehaviorTemplates : unsigned int {
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors
BEHAVIOR_BASIC_ATTACK,
BEHAVIOR_TAC_ARC,
BEHAVIOR_AND,
BEHAVIOR_PROJECTILE_ATTACK,
BEHAVIOR_HEAL,
BEHAVIOR_MOVEMENT_SWITCH,
BEHAVIOR_AREA_OF_EFFECT,
BEHAVIOR_PLAY_EFFECT,
BEHAVIOR_IMMUNITY,
BEHAVIOR_DAMAGE_BUFF,
BEHAVIOR_DAMAGE_ABSORBTION,
BEHAVIOR_OVER_TIME,
BEHAVIOR_IMAGINATION,
BEHAVIOR_TARGET_CASTER,
BEHAVIOR_STUN,
BEHAVIOR_DURATION,
BEHAVIOR_KNOCKBACK,
BEHAVIOR_ATTACK_DELAY,
BEHAVIOR_CAR_BOOST,
BEHAVIOR_FALL_SPEED,
BEHAVIOR_SHIELD,
BEHAVIOR_REPAIR_ARMOR,
BEHAVIOR_SPEED,
BEHAVIOR_DARK_INSPIRATION,
BEHAVIOR_LOOT_BUFF,
BEHAVIOR_VENTURE_VISION,
BEHAVIOR_SPAWN_OBJECT,
BEHAVIOR_LAY_BRICK,
BEHAVIOR_SWITCH,
BEHAVIOR_BUFF,
BEHAVIOR_JETPACK,
BEHAVIOR_SKILL_EVENT,
BEHAVIOR_CONSUME_ITEM,
BEHAVIOR_SKILL_CAST_FAILED,
BEHAVIOR_IMITATION_SKUNK_STINK,
BEHAVIOR_CHANGE_IDLE_FLAGS,
BEHAVIOR_APPLY_BUFF,
BEHAVIOR_CHAIN,
BEHAVIOR_CHANGE_ORIENTATION,
BEHAVIOR_FORCE_MOVEMENT,
BEHAVIOR_INTERRUPT,
BEHAVIOR_ALTER_COOLDOWN,
BEHAVIOR_CHARGE_UP,
BEHAVIOR_SWITCH_MULTIPLE,
BEHAVIOR_START,
BEHAVIOR_END,
BEHAVIOR_ALTER_CHAIN_DELAY,
BEHAVIOR_CAMERA,
BEHAVIOR_REMOVE_BUFF,
BEHAVIOR_GRAB,
BEHAVIOR_MODULAR_BUILD,
BEHAVIOR_NPC_COMBAT_SKILL,
BEHAVIOR_BLOCK,
BEHAVIOR_VERIFY,
BEHAVIOR_TAUNT,
BEHAVIOR_AIR_MOVEMENT,
BEHAVIOR_SPAWN_QUICKBUILD,
BEHAVIOR_PULL_TO_POINT,
BEHAVIOR_PROPERTY_ROTATE,
BEHAVIOR_DAMAGE_REDUCTION,
BEHAVIOR_PROPERTY_TELEPORT,
BEHAVIOR_PROPERTY_CLEAR_TARGET,
BEHAVIOR_TAKE_PICTURE,
BEHAVIOR_MOUNT,
BEHAVIOR_SKILL_SET
};

View File

@@ -7,7 +7,6 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
"Behavior.cpp"
"BehaviorBranchContext.cpp"
"BehaviorContext.cpp"
"BehaviorTemplates.cpp"
"BlockBehavior.cpp"
"BuffBehavior.cpp"
"CarBoostBehavior.cpp"

View File

@@ -7,7 +7,7 @@
#include "Logger.h"
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}
@@ -38,7 +38,7 @@ void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bi
}
void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}

View File

@@ -6,13 +6,13 @@
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
uint32_t movementType{};
if (!bitStream.Read(movementType)) {
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
@@ -47,7 +47,7 @@ void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) {
float actionValue = GetFloat(movementType, -1.0f);
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) {
loadedBehavior = this->m_groundAction;
}
return loadedBehavior;

View File

@@ -9,17 +9,16 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
}
}
void
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
void SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
}
}

View File

@@ -7,9 +7,9 @@
#include "BuffComponent.h"
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
auto state = true;
bool state = true;
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
if (!bitStream.Read(state)) {
LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
@@ -18,49 +18,59 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
auto* entity = Game::entityManager->GetEntity(context->originator);
if (entity == nullptr) {
return;
}
if (!entity) return;
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr) {
return;
if (destroyableComponent) {
if (m_isEnemyFaction) {
auto* target = Game::entityManager->GetEntity(branch.target);
if (target) state = destroyableComponent->IsEnemy(target);
}
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
}
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
if (state) {
this->m_actionTrue->Handle(context, bitStream, branch);
} else {
this->m_actionFalse->Handle(context, bitStream, branch);
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Handle(context, bitStream, branch);
}
void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto state = true;
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
bool state = true;
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
auto* entity = Game::entityManager->GetEntity(branch.target);
state = entity != nullptr;
if (state && m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (state) {
if (m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
state = false;
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
state = false;
}
} else if (m_imagination > 0) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent && destroyableComponent->GetImagination() < m_imagination) {
state = false;
}
} else if (m_Distance > -1.0f) {
auto* originator = Game::entityManager->GetEntity(context->originator);
if (originator) {
const auto distance = (originator->GetPosition() - entity->GetPosition()).Length();
state = distance <= m_Distance;
}
}
}
bitStream.Write(state);
}
if (state) {
this->m_actionTrue->Calculate(context, bitStream, branch);
} else {
this->m_actionFalse->Calculate(context, bitStream, branch);
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Calculate(context, bitStream, branch);
}
void SwitchBehavior::Load() {
@@ -72,5 +82,7 @@ void SwitchBehavior::Load() {
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
this->m_targetHasBuff = GetInt("target_has_buff");
this->m_targetHasBuff = GetInt("target_has_buff", -1);
this->m_Distance = GetFloat("distance", -1.0f);
}

View File

@@ -14,6 +14,8 @@ public:
int32_t m_targetHasBuff;
float m_Distance;
/*
* Inherited
*/

View File

@@ -162,7 +162,6 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
// Check if we should stop the tether effect
if (m_TetherEffectActive) {
m_TetherTime -= deltaTime;
const auto& info = m_MovementAI->GetInfo();
if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared(
m_StartPosition,
m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0)

View File

@@ -50,9 +50,42 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_CurrentSpeed = 0;
m_MaxSpeed = 0;
m_LockRotation = false;
m_Path = nullptr;
m_SourcePosition = m_Parent->GetPosition();
m_Paused = false;
m_SavedVelocity = NiPoint3Constant::ZERO;
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
}
void MovementAIComponent::SetPath(const std::string pathName) {
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
if (!pathName.empty()) LOG("WARNING: %s path %s", m_Path ? "Found" : "Failed to find", pathName.c_str());
if (!m_Path) return;
SetMaxSpeed(1);
SetCurrentSpeed(m_BaseSpeed);
SetPath(m_Path->pathWaypoints);
}
void MovementAIComponent::Pause() {
m_Paused = true;
SetPosition(ApproximateLocation());
m_SavedVelocity = GetVelocity();
SetVelocity(NiPoint3Constant::ZERO);
Game::entityManager->SerializeEntity(m_Parent);
}
void MovementAIComponent::Resume() {
m_Paused = false;
SetVelocity(m_SavedVelocity);
m_SavedVelocity = NiPoint3Constant::ZERO;
SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), m_NextWaypoint));
Game::entityManager->SerializeEntity(m_Parent);
}
void MovementAIComponent::Update(const float deltaTime) {
if (m_Paused) return;
if (m_PullingToPoint) {
const auto source = GetCurrentWaypoint();
@@ -81,64 +114,65 @@ void MovementAIComponent::Update(const float deltaTime) {
}
m_TimeTravelled += deltaTime;
SetPosition(ApproximateLocation());
if (m_TimeTravelled < m_TimeToTravel) return;
m_TimeTravelled = 0.0f;
const auto source = GetCurrentWaypoint();
SetPosition(source);
NiPoint3 velocity = NiPoint3Constant::ZERO;
m_SourcePosition = source;
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
{
m_NextWaypoint = GetCurrentWaypoint();
if (m_NextWaypoint == source) {
m_TimeToTravel = 0.0f;
} else {
m_CurrentSpeed = std::min(m_CurrentSpeed + m_Acceleration, m_MaxSpeed);
goto nextAction;
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
const auto delta = m_NextWaypoint - source;
// Normalize the vector
const auto length = delta.Length();
if (length > 0.0f) {
SetVelocity((delta / length) * speed);
}
// Calclute the time it will take to reach the next waypoint with the current speed
m_TimeTravelled = 0.0f;
m_TimeToTravel = length / speed;
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
}
if (m_CurrentSpeed < m_MaxSpeed) {
m_CurrentSpeed += m_Acceleration;
}
if (m_CurrentSpeed > m_MaxSpeed) {
m_CurrentSpeed = m_MaxSpeed;
}
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
const auto delta = m_NextWaypoint - source;
// Normalize the vector
const auto length = delta.Length();
if (length > 0) {
velocity = (delta / length) * speed;
}
// Calclute the time it will take to reach the next waypoint with the current speed
m_TimeTravelled = 0.0f;
m_TimeToTravel = length / speed;
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
} else {
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
if (m_CurrentPath.empty()) {
Stop();
return;
if (m_Path) {
if (m_Path->pathBehavior == PathBehavior::Loop) {
SetPath(m_Path->pathWaypoints);
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
std::reverse(waypoints.begin(), waypoints.end());
SetPath(waypoints);
} else if (m_Path->pathBehavior == PathBehavior::Once) {
Stop();
return;
}
} else {
Stop();
return;
}
}
SetDestination(m_CurrentPath.top());
SetDestination(m_CurrentPath.top().position);
m_CurrentPath.pop();
}
nextAction:
SetVelocity(velocity);
Game::entityManager->SerializeEntity(m_Parent);
}
@@ -161,7 +195,7 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
}
NiPoint3 MovementAIComponent::ApproximateLocation() const {
auto source = m_Parent->GetPosition();
auto source = m_SourcePosition;
if (AtFinalWaypoint()) return source;
@@ -227,13 +261,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
m_PullPoint = point;
}
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) {
if (path.empty()) return;
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
std::for_each(path.rbegin(), path.rend() - 1, [this](const PathWaypoint& point) {
this->m_CurrentPath.push(point);
});
SetDestination(path.front());
SetDestination(path.front().position);
}
float MovementAIComponent::GetBaseSpeed(LOT lot) {
@@ -278,6 +312,23 @@ void MovementAIComponent::SetRotation(const NiQuaternion& value) {
if (!m_LockRotation) m_Parent->SetRotation(value);
}
NiPoint3 MovementAIComponent::GetVelocity() const {
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent != nullptr) {
return controllablePhysicsComponent->GetVelocity();
}
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
if (simplePhysicsComponent != nullptr) {
return simplePhysicsComponent->GetVelocity();
}
return NiPoint3Constant::ZERO;
}
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
@@ -294,7 +345,7 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) {
}
}
void MovementAIComponent::SetDestination(const NiPoint3& destination) {
void MovementAIComponent::SetDestination(const NiPoint3 destination) {
if (m_PullingToPoint) return;
const auto location = ApproximateLocation();
@@ -303,6 +354,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
SetPosition(location);
}
m_SourcePosition = location;
std::vector<NiPoint3> computedPath;
if (dpWorld::IsLoaded()) {
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
@@ -319,8 +372,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
auto step = delta / 10.0f;
for (int i = 0; i < 10; i++) {
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
start = start + step;
start += step;
computedPath.push_back(start);
}

View File

@@ -14,11 +14,14 @@
#include "Logger.h"
#include "Component.h"
#include "eReplicaComponentType.h"
#include "Zone.h"
#include <vector>
class ControllablePhysicsComponent;
class BaseCombatAIComponent;
struct Path;
/**
* Information that describes the different variables used to make an entity move around
*/
@@ -61,6 +64,8 @@ public:
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
void SetPath(const std::string pathName);
void Update(float deltaTime) override;
/**
@@ -73,7 +78,7 @@ public:
* Set a destination point for the entity to move towards
* @param value the destination point to move towards
*/
void SetDestination(const NiPoint3& value);
void SetDestination(const NiPoint3 value);
/**
* Returns the current rotation this entity is moving towards
@@ -189,7 +194,13 @@ public:
* Sets a path to follow for the AI
* @param path the path to follow
*/
void SetPath(std::vector<NiPoint3> path);
void SetPath(std::vector<PathWaypoint> path);
void Pause();
void Resume();
NiPoint3 GetVelocity() const;
/**
* Returns the base speed from the DB for a given LOT
@@ -301,7 +312,15 @@ private:
/**
* The path from the current position to the destination.
*/
std::stack<NiPoint3> m_CurrentPath;
std::stack<PathWaypoint> m_CurrentPath;
const Path* m_Path = nullptr;
NiPoint3 m_SourcePosition;
bool m_Paused;
NiPoint3 m_SavedVelocity;
};
#endif // MOVEMENTAICOMPONENT_H

View File

@@ -64,6 +64,7 @@ void ProximityMonitorComponent::Update(float deltaTime) {
for (const auto& prox : m_ProximitiesData) {
if (!prox.second) continue;
prox.second->SetPosition(m_Parent->GetPosition());
//Process enter events
for (auto* en : prox.second->GetNewObjects()) {
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER");

View File

@@ -5,7 +5,6 @@
void WanderingVendor::OnStartup(Entity* self) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->Resume();
self->SetProximityRadius(10, "playermonitor");
}
@@ -13,7 +12,7 @@ void WanderingVendor::OnProximityUpdate(Entity* self, Entity* entering, std::str
if (status == "ENTER" && entering->IsPlayer()) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->Pause();
movementAIComponent->Pause();
self->CancelTimer("startWalking");
} else if (status == "LEAVE") {
auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>();
@@ -28,6 +27,6 @@ void WanderingVendor::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "startWalking") {
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->Resume();
movementAIComponent->Resume();
}
}

View File

@@ -307,11 +307,7 @@ void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
movementAI->SetHaltDistance(0.0f);
std::vector<NiPoint3> pathWaypoints;
for (const auto& waypoint : path->pathWaypoints) {
pathWaypoints.push_back(waypoint.position);
}
std::vector<PathWaypoint> pathWaypoints = path->pathWaypoints;
if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
std::reverse(pathWaypoints.begin(), pathWaypoints.end());

View File

@@ -5,20 +5,19 @@
void WblRobotCitizen::OnStartup(Entity* self) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->Resume();
}
void WblRobotCitizen::OnUse(Entity* self, Entity* user) {
// auto movementAIComponent = self->GetComponent<MovementAIComponent>();
// if (!movementAIComponent) movementAIComponent->Pause();
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (movementAIComponent) movementAIComponent->Pause();
auto face = NiQuaternion::LookAt(self->GetPosition(), user->GetPosition());
self->SetRotation(face);
auto timer = RenderComponent::PlayAnimation(self, "wave");
auto timer = RenderComponent::PlayAnimation(self, "wave", 0.4f);
self->AddTimer("animation time", timer);
}
void WblRobotCitizen::OnTimerDone(Entity* self, std::string timerName) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->Resume();
movementAIComponent->Resume();
}

View File

@@ -16,57 +16,57 @@ class Level;
enum class eWaypointCommandType : uint32_t;
struct WaypointCommand {
eWaypointCommandType command;
eWaypointCommandType command{};
std::string data;
};
struct SceneRef {
std::string filename;
uint32_t id;
uint32_t sceneType; //0 = general, 1 = audio?
uint32_t id{};
uint32_t sceneType{}; //0 = general, 1 = audio?
std::string name;
NiPoint3 unknown1;
float unknown2;
uint8_t color_r;
uint8_t color_g;
uint8_t color_b;
float unknown2{};
uint8_t color_r{};
uint8_t color_g{};
uint8_t color_b{};
Level* level;
std::map<uint32_t, LUTriggers::Trigger*> triggers;
};
struct SceneTransitionInfo {
uint64_t sceneID; //id of the scene being transitioned to.
uint64_t sceneID{}; //id of the scene being transitioned to.
NiPoint3 position;
};
struct SceneTransition {
std::string name;
std::vector<SceneTransitionInfo> points;
float width;
float width{};
};
struct MovingPlatformPathWaypoint {
uint8_t lockPlayer;
float wait;
uint8_t lockPlayer{};
float wait{};
std::string departSound;
std::string arriveSound;
};
struct CameraPathWaypoint {
float time;
float fov;
float tension;
float continuity;
float bias;
float time{};
float fov{};
float tension{};
float continuity{};
float bias{};
};
struct RacingPathWaypoint {
uint8_t isResetNode;
uint8_t isNonHorizontalCamera;
float planeWidth;
float planeHeight;
float shortestDistanceToEnd;
uint8_t isResetNode{};
uint8_t isNonHorizontalCamera{};
float planeWidth{};
float planeHeight{};
float shortestDistanceToEnd{};
};
struct PathWaypoint {
@@ -75,7 +75,7 @@ struct PathWaypoint {
MovingPlatformPathWaypoint movingPlatform;
CameraPathWaypoint camera;
RacingPathWaypoint racing;
float speed;
float speed{};
std::vector<LDFBaseData*> config;
std::vector<WaypointCommand> commands;
};
@@ -137,49 +137,49 @@ enum class PropertyAchievmentRequired : uint32_t {
struct MovingPlatformPath {
std::string platformTravelSound;
uint8_t timeBasedMovement;
uint8_t timeBasedMovement{};
};
struct PropertyPath {
PropertyPathType pathType;
int32_t price;
uint32_t rentalTime;
uint64_t associatedZone;
PropertyPathType pathType{};
int32_t price{};
uint32_t rentalTime{};
uint64_t associatedZone{};
std::string displayName;
std::string displayDesc;
PropertyType type;
uint32_t cloneLimit;
float repMultiplier;
PropertyRentalPeriod rentalPeriod;
PropertyAchievmentRequired achievementRequired;
PropertyType type{};
uint32_t cloneLimit{};
float repMultiplier{};
PropertyRentalPeriod rentalPeriod{};
PropertyAchievmentRequired achievementRequired{};
// Player respawn coordinates in the main zone (not the property zone)
NiPoint3 playerZoneCoords;
float maxBuildHeight;
float maxBuildHeight{};
};
struct CameraPath {
std::string nextPath;
uint8_t rotatePlayer;
uint8_t rotatePlayer{};
};
struct SpawnerPath {
LOT spawnedLOT;
uint32_t respawnTime;
int32_t maxToSpawn;
uint32_t amountMaintained;
LOT spawnedLOT{};
uint32_t respawnTime{};
int32_t maxToSpawn{};
uint32_t amountMaintained{};
LWOOBJID spawnerObjID;
uint8_t spawnerNetActive;
uint8_t spawnerNetActive{};
};
struct Path {
uint32_t pathVersion;
uint32_t pathVersion{};
PathType pathType;
std::string pathName;
uint32_t flags;
uint32_t flags{};
PathBehavior pathBehavior;
uint32_t waypointCount;
uint32_t waypointCount{};
std::vector<PathWaypoint> pathWaypoints;
SpawnerPath spawner;
MovingPlatformPath movingPlatform;

View File

@@ -11,7 +11,7 @@ ALTER TABLE leaderboard CHANGE time secondaryScore FLOAT NOT NULL DEFAULT 0 AFTE
/* A bit messy, but better than going through a bunch of code fixes all to be run once. */
UPDATE leaderboard SET
primaryScore = secondaryScore,
secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901);
secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901) AND secondaryScore > 0;
/* Do this last so we dont update entry times erroneously */
ALTER TABLE leaderboard