/koruma 2642 150 yazınca
150 tane korumanız oluyor.
sornada brine saldırınca o oyuncuya saldıramya başlıyorlar.
serbest modda herkese saldırıyorlar.
/m 2642
/koruma 2643
korumaların m 2642 saldırmıyor.
ama koruma oalrak
/koruma 11003 köy gardiyanı çağırdığında köy gardiyanı saldırıyor.
köy gardiyanın harkeet etmesini isityorsanda mob protadan hızını eklemen lazım yoksa sabit duruyor
mob proto köy gardiyanı update
Kod:
NOMOVE 0
kısmı şu şekilde yapıldı
MELEE 1
diyelim x oyuncu koruma olarak
bi canavar çağırdığı
y oyuncusuda koruma olarak mavi bayrak olmasına rağmen sarı bayrak köy gardiyanı çağırdı
bu durumda y oyuncusunun koruması x oyuncusunun hem yaratığına hemde korumasına saldırır.
videokdaki gibi

Kod:
150 tane korumanız oluyor.
sornada brine saldırınca o oyuncuya saldıramya başlıyorlar.
serbest modda herkese saldırıyorlar.
/m 2642
/koruma 2643
korumaların m 2642 saldırmıyor.
ama koruma oalrak
/koruma 11003 köy gardiyanı çağırdığında köy gardiyanı saldırıyor.
köy gardiyanın harkeet etmesini isityorsanda mob protadan hızını eklemen lazım yoksa sabit duruyor
mob proto köy gardiyanı update
Kod:
11000 °æºñº´ KNIGHT NPC MELEE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 1 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11001 °æºñº´ KNIGHT NPC RANGE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 1 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11002 °æºñº´ KNIGHT NPC MELEE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 2 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11003 °æºñº´ KNIGHT NPC RANGE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 2 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11004 °æºñº´ KNIGHT NPC MELEE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 3 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11005 °æºñº´ KNIGHT NPC RANGE 100 MELEE 1 STUN,SLOW,CURSE,TERROR 3 2 0 0 0 0 0 0 6938 3 1 0 0 802 109 100 100 0 2000 175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
NOMOVE 0
kısmı şu şekilde yapıldı
MELEE 1
diyelim x oyuncu koruma olarak
bi canavar çağırdığı
y oyuncusuda koruma olarak mavi bayrak olmasına rağmen sarı bayrak köy gardiyanı çağırdı
bu durumda y oyuncusunun koruması x oyuncusunun hem yaratığına hemde korumasına saldırır.
videokdaki gibi

Kod:
cmd_cpp
ACMD(do_koruma_ordu);
ACMD(do_koruma_temizle);
{ "koruma", do_koruma_ordu, 0, POS_DEAD, GM_PLAYER },
{ "koruma_temizle", do_koruma_temizle, 0, POS_DEAD, GM_PLAYER },
cmd_general.cpp
#include <unordered_map>
#include <vector>
#include <string_view>
#include <charconv>
#include "event.h"
#include "pvp.h"
#include "guild_manager.h"
#include "guild.h"
// --- ORDU HAFIZASI (C++20 Standartlarında Global Liste) ---
// Hangi oyuncunun (PID), hangi korumalara (VID listesi) sahip oldu?unu aklında tutar
static std::unordered_map<uint32_t, std::vector<uint32_t>> g_bodyguard_map;
// --- KORUMA S?STEM? B?LG? YAPISI ---
EVENTINFO(BodyguardEventInfo)
{
uint32_t owner_pid;
uint32_t guard_vid;
long last_goto_x; // Animasyon kilidini acan hafıza
long last_goto_y;
BodyguardEventInfo() : owner_pid{0}, guard_vid{0}, last_goto_x{0}, last_goto_y{0} {}
};
// --- ORDU YAPAY ZEKA DONGUSU (Her bir koruma icin ayrı calı?ır) ---
EVENTFUNC(bodyguard_event_func)
{
auto* info{static_cast<BodyguardEventInfo*>(event->info)};
if (!info)
return 0;
auto* owner{CHARACTER_MANAGER::instance().FindByPID(info->owner_pid)};
auto* guard{CHARACTER_MANAGER::instance().Find(info->guard_vid)};
if (!owner || !guard || guard->IsDead() || owner->IsDead())
{
if (guard && !guard->IsDead()) guard->Dead();
return 0;
}
// --- 1. MESAFE VE I?INLANMA KONTROLU ---
constexpr int max_follow_dist{2500};
if (owner->GetMapIndex() != guard->GetMapIndex() ||
DISTANCE_APPROX(owner->GetX() - guard->GetX(), owner->GetY() - guard->GetY()) > max_follow_dist)
{
guard->Show(owner->GetMapIndex(), owner->GetX() + number(-200, 200), owner->GetY() + number(-200, 200), owner->GetZ());
guard->UpdatePacket();
guard->SetVictim(nullptr);
guard->Stop();
return PASSES_PER_SEC(1);
}
// --- 2. SENKRON?ZE HEDEFLEME (FOCUS FIRE) - DUZELT?LD? ---
// ONCEL?K 1: Sahibin o an vurdu?u veya secti?i hedef
LPCHARACTER primary_target{owner->GetVictim()};
// ONCEL?K 2: E?er sahibin hedefi yoksa, korumanın kendisine saldıran du?man
if (!primary_target)
primary_target = guard->GetVictim();
if (primary_target && primary_target != owner && !primary_target->IsDead() && primary_target->GetMapIndex() == owner->GetMapIndex())
{
bool can_attack{false};
// PvP ve PvE Kuralları Kontrolu
if (!primary_target->IsPC()) can_attack = true;
else
{
if (owner->GetPKMode() == PK_MODE_FREE) can_attack = true;
else if (CPVPManager::instance().IsFighting(owner)) can_attack = true;
else if (owner->GetEmpire() != primary_target->GetEmpire() && owner->GetPKMode() != PK_MODE_PROTECT) can_attack = true;
else if (owner->GetGuild() && primary_target->GetGuild() && owner->GetGuild()->UnderWar(primary_target->GetGuild()->GetID())) can_attack = true;
}
if (can_attack)
{
if (guard->GetVictim() != primary_target)
{
guard->SetVictim(primary_target);
// Canavarı agresif moda sok (State tetiklemesi)
guard->SetRotationToXY(primary_target->GetX(), primary_target->GetY());
}
return PASSES_PER_SEC(1);
}
}
// E?er gecerli bir hedef yoksa sava?ı bırak
if (guard->GetVictim())
guard->SetVictim(nullptr);
// --- 3. SAVA? YOKSA SAH?B?N? TAK?P ET ---
constexpr int min_follow_dist{450};
if (DISTANCE_APPROX(owner->GetX() - guard->GetX(), owner->GetY() - guard->GetY()) > min_follow_dist)
{
constexpr int update_threshold{250};
if (DISTANCE_APPROX(owner->GetX() - info->last_goto_x, owner->GetY() - info->last_goto_y) > update_threshold)
{
// Ordu takip ederken birbirinin icine girmemesi icin hafif da?ılım veriyoruz
int target_x = owner->GetX() + number(-250, 250);
int target_y = owner->GetY() + number(-250, 250);
guard->SetRotationToXY(target_x, target_y);
guard->Goto(target_x, target_y);
info->last_goto_x = owner->GetX();
info->last_goto_y = owner->GetY();
}
}
return PASSES_PER_SEC(1);
}
// --- KOMUT 1: ORDU CA?IR (/koruma <mob_kodu> <adet>) ---
ACMD(do_koruma_ordu)
{
if (!ch) return;
char arg1[256], arg2[256];
// Kullanıcının 2 parametre (Kod ve Adet) girebilmesi icin two_arguments kullanıyoruz
two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
std::string_view vnum_str{arg1};
std::string_view count_str{arg2};
if (vnum_str.empty())
{
ch->ChatPacket(CHAT_TYPE_INFO, "Kullanım: /koruma <canavar_kodu> [adet]");
ch->ChatPacket(CHAT_TYPE_INFO, "Ornek: /koruma 2642 50 (50 tane dev akrep ca?ırır)");
ch->ChatPacket(CHAT_TYPE_INFO, "Tum orduyu silmek icin: /koruma_temizle");
return;
}
uint32_t mob_vnum{0};
auto [ptr1, ec1] = std::from_chars(vnum_str.data(), vnum_str.data() + vnum_str.size(), mob_vnum);
if (ec1 != std::errc())
{
ch->ChatPacket(CHAT_TYPE_INFO, "Gecerli bir canavar kodu girin.");
return;
}
uint32_t count{1}; // Adet girilmezse varsayılan olarak 1 tane ca?ırır
if (!count_str.empty())
{
std::from_chars(count_str.data(), count_str.data() + count_str.size(), count);
}
// Sunucuyu cokertmemek icin guvenlik limiti (Tek seferde max 300)
if (count > 300)
{
count = 300;
ch->ChatPacket(CHAT_TYPE_INFO, "Guvenlik sebebiyle tek seferde en fazla 300 koruma ca?ırılabilir.");
}
for (uint32_t i = 0; i < count; ++i)
{
// Korumaları etrafa rastgele bir cember ?eklinde da?ıt (Scatter sistemi)
int random_x = ch->GetX() + number(-500, 500);
int random_y = ch->GetY() + number(-500, 500);
auto* guard{CHARACTER_MANAGER::instance().SpawnMob(mob_vnum, ch->GetMapIndex(), random_x, random_y, ch->GetZ(), false, -1, false)};
if (!guard) continue;
guard->SetEmpire(ch->GetEmpire());
guard->SetLevel(ch->GetLevel());
char name_buf[128];
snprintf(name_buf, sizeof(name_buf), "[Ordu] %s", ch->GetName());
guard->SetName(name_buf);
// Korumayı do?rudan global ordu listesine (Hafızaya) kaydediyoruz
g_bodyguard_map[ch->GetPlayerID()].push_back(guard->GetVID());
auto* info{AllocEventInfo<BodyguardEventInfo>()};
info->owner_pid = ch->GetPlayerID();
info->guard_vid = guard->GetVID();
info->last_goto_x = ch->GetX();
info->last_goto_y = ch->GetY();
event_create(bodyguard_event_func, info, PASSES_PER_SEC(1));
}
ch->ChatPacket(CHAT_TYPE_INFO, "%u adet %u kodlu koruma orduna katıldı!", count, mob_vnum);
}
// --- KOMUT 2: ORDUYU DA?IT (/koruma_temizle) ---
ACMD(do_koruma_temizle)
{
if (!ch) return;
// Oyuncunun ordusunu hafızadan bul
auto it = g_bodyguard_map.find(ch->GetPlayerID());
// E?er oyuncunun hic ordusu yoksa
if (it == g_bodyguard_map.end() || it->second.empty())
{
ch->ChatPacket(CHAT_TYPE_INFO, "?u anda seni takip eden bir koruma ordun yok.");
return;
}
uint32_t killed_count{0};
// Listedeki tum VIDs (Virtual ID) numaralarını tek tek bul ve oldur
for (uint32_t vid : it->second)
{
auto* guard = CHARACTER_MANAGER::instance().Find(vid);
if (guard && !guard->IsDead())
{
guard->Dead();
killed_count++;
}
}
// Listeyi tamamen temizle
it->second.clear();
ch->ChatPacket(CHAT_TYPE_INFO, "Toplam %u koruma birli?in da?ıtıldı ve evine gonderildi.", killed_count);
}


