Working on enemies and attack

This commit is contained in:
Vladislav Khorev 2026-04-15 10:00:16 +03:00
parent 493eb5a5d7
commit 984d7489d5
7 changed files with 855630 additions and 24 deletions

View File

@ -21,28 +21,6 @@
"description": "A token from the Guard - sign of respect", "description": "A token from the Guard - sign of respect",
"icon": "resources/fire2.png" "icon": "resources/fire2.png"
} }
},
{
"id": "npc_02_ghost",
"name": "NPC Floating Ghost",
"texturePath": "resources/w/ghost_skin001.png",
"animationIdlePath": "resources/w/default_float001.txt",
"animationWalkPath": "resources/w/default_float001.txt",
"positionX": 0.0,
"positionY": 0.0,
"positionZ": -20.0,
"walkSpeed": 1.5,
"rotationSpeed": 8.0,
"modelScale": 0.01,
"modelCorrectionRotX": 0.0,
"modelCorrectionRotY": 180.0,
"modelCorrectionRotZ": 0.0,
"gift": {
"id": "ghost_essence",
"name": "Ghost's Essence",
"description": "A mysterious essence from the Ghost realm",
"icon": "resources/fire2.png"
}
} }
] ]
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
namespace ZL { namespace ZL {
const float ATTACK_COOLDOWN_TIME = 3.0f;
void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) { void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) {
auto& data = animations[state]; auto& data = animations[state];
data.model.LoadFromFile(filename, zipFile); data.model.LoadFromFile(filename, zipFile);
@ -83,6 +85,16 @@ void Character::update(int64_t deltaMs) {
resetAnim = true; resetAnim = true;
} }
if (canAttack && attack == 0 && attack_cooldown < 0.f && currentState == AnimationState::ACTION_IDLE)
{
attack = 1;
attack_cooldown = ATTACK_COOLDOWN_TIME;
}
if (canAttack && attack_cooldown >= 0.f)
{
attack_cooldown = attack_cooldown - deltaMs / 1000.f;
}
if (attack == 1 && currentState == AnimationState::ACTION_IDLE) if (attack == 1 && currentState == AnimationState::ACTION_IDLE)
{ {
currentState = AnimationState::ACTION_ATTACK; currentState = AnimationState::ACTION_ATTACK;

View File

@ -55,6 +55,8 @@ public:
bool resetAnim = false; bool resetAnim = false;
int attack = 0; int attack = 0;
AnimationState currentState = AnimationState::STAND; AnimationState currentState = AnimationState::STAND;
float attack_cooldown = 0.f;
bool canAttack = false;
private: private:
struct AnimationData { struct AnimationData {

View File

@ -175,6 +175,7 @@ namespace ZL
/*Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) * */ /*Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) * */
/*Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));*/ /*Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));*/
player->canAttack = true;
std::cout << "Load resurces step 9" << std::endl; std::cout << "Load resurces step 9" << std::endl;
// Load NPCs from JSON // Load NPCs from JSON
@ -201,11 +202,19 @@ namespace ZL
npc01->setTarget(npc01->position); npc01->setTarget(npc01->position);
npcs.push_back(std::move(npc01)); npcs.push_back(std::move(npc01));
*/
auto ghostTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/ghost_skin001.png", CONST_ZIP_FILE)); auto ghostTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/ghost_skin001.png", CONST_ZIP_FILE));
std::cout << "Load resurces step 11" << std::endl; std::cout << "Load resurces step 11" << std::endl;
auto npc02 = std::make_unique<Character>(); auto npc02 = std::make_unique<Character>();
npc02->loadAnimation(AnimationState::STAND, "resources/w/default_float001.txt", CONST_ZIP_FILE); npc02->loadAnimation(AnimationState::STAND, "resources/w/default_float001.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::WALK, "resources/w/default_float001.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::ACTION_IDLE, "resources/w/float_attack003_cut.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::ACTION_ATTACK, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::STAND_TO_ACTION, "resources/w/default_float001_cut.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::ACTION_TO_STAND, "resources/w/default_float001_cut.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::STAND, "resources/w/float_attack003.txt", CONST_ZIP_FILE); //npc02->loadAnimation(AnimationState::STAND, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::STAND, "resources/idleviola_uv010.txt", CONST_ZIP_FILE); //npc02->loadAnimation(AnimationState::STAND, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
npc02->setTexture(ghostTexture); npc02->setTexture(ghostTexture);
@ -217,10 +226,11 @@ namespace ZL
npc02->position = Eigen::Vector3f(0.f, 0.f, -20.f); npc02->position = Eigen::Vector3f(0.f, 0.f, -20.f);
npc02->setTarget(npc02->position); npc02->setTarget(npc02->position);
npc02->canAttack = true;
npcs.push_back(std::move(npc02)); npcs.push_back(std::move(npc02));
std::cout << "Load resurces step 12" << std::endl; std::cout << "Load resurces step 12" << std::endl;
*/
loadingCompleted = true; loadingCompleted = true;
@ -497,6 +507,65 @@ namespace ZL
if (player) player->update(delta); if (player) player->update(delta);
for (auto& npc : npcs) npc->update(delta); for (auto& npc : npcs) npc->update(delta);
for (auto& npc : npcs)
{
if (npc->canAttack)
{
float distToGhost = (player->position - npc->position).norm();
if (distToGhost >= 10.f)
{
if (npc->battle_state != 0)
{
npc->battle_state = 0;
}
}
else if (distToGhost < 10.0f && distToGhost >= 1.f) {
npc->setTarget(player->position);
if (npc->battle_state != 0)
{
npc->battle_state = 0;
}
}
else
{
npc->setTarget(npc->position);
if (npc->battle_state != 1)
{
npc->battle_state = 1;
}
}
}
}
if (playerAttackTarget != nullptr)
{
auto pos = playerAttackTarget->position;
float distToTarget = (player->position - pos).norm();
if (distToTarget > 1.0)
{
player->setTarget(Eigen::Vector3f(pos.x(), 0.f, pos.z()));
}
else
{
if (player->battle_state != 1)
{
player->setTarget(player->position);
player->battle_state = 1;
//player->attack = 1;
}
}
}
if (playerAttackTarget == nullptr)
{
if (player->battle_state != 0)
{
player->battle_state = 0;
player->attack = 0;
}
}
// Check if player reached target interactive object // Check if player reached target interactive object
if (targetInteractiveObject && player) { if (targetInteractiveObject && player) {
float distToObject = (player->position - targetInteractiveObject->position).norm(); float distToObject = (player->position - targetInteractiveObject->position).norm();
@ -529,6 +598,12 @@ namespace ZL
dialogueSystem.update(static_cast<int>(delta), player->position); dialogueSystem.update(static_cast<int>(delta), player->position);
} }
} }
// Some AI stuff
} }
} }
@ -616,6 +691,8 @@ namespace ZL
std::cout << "\n========== MOUSE DOWN EVENT ==========" << std::endl; std::cout << "\n========== MOUSE DOWN EVENT ==========" << std::endl;
handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my); handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
playerAttackTarget = nullptr;
// Calculate ray for picking // Calculate ray for picking
if (dialogueSystem.blocksGameplayInput()) { if (dialogueSystem.blocksGameplayInput()) {
dialogueSystem.handlePointerReleased(static_cast<float>(mx), Environment::projectionHeight - static_cast<float>(my)); dialogueSystem.handlePointerReleased(static_cast<float>(mx), Environment::projectionHeight - static_cast<float>(my));
@ -669,6 +746,12 @@ namespace ZL
if (npcIndex != -1) { if (npcIndex != -1) {
std::cout << "[CLICK] *** SUCCESS: Clicked on NPC index: " << npcIndex << " ***" << std::endl; std::cout << "[CLICK] *** SUCCESS: Clicked on NPC index: " << npcIndex << " ***" << std::endl;
scriptEngine.callNpcInteractCallback(npcIndex); scriptEngine.callNpcInteractCallback(npcIndex);
if (clickedNpc->canAttack)
{
playerAttackTarget = clickedNpc;
}
} }
} }
else if (rayDir.y() < -0.001f && player) { else if (rayDir.y() < -0.001f && player) {

View File

@ -84,6 +84,7 @@ namespace ZL {
// Public access for ScriptEngine // Public access for ScriptEngine
MenuManager menuManager; MenuManager menuManager;
ScriptEngine scriptEngine; ScriptEngine scriptEngine;
Character* playerAttackTarget = nullptr;
private: private:
bool rightMouseDown = false; bool rightMouseDown = false;