Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

help to add customization to MUEMU or IGCN source

Joined
Aug 29, 2011
Messages
512
Reaction score
33
I'm looking for someone who knows how to program, who can add this custom that has on the ZTeam eX802 muserver, so that it can be added to IGCN season 9 or X-Team Season 8 source.

it's the MonsterSpawner.xml

in Red is define an item that when it is dropped will create a Temporary Spot
in Yellow is defined the monster that will spawn and also the quantity and the duration time.
in Green it is defined if the spot created will be private or not (if it is deprived only those who dropped the item can attack the monsters.
in Blue is defined if the party of whom the item drops will be able to attack.
in Orange is set if the guild of who drops the item will be able to attack.

<monsterspawner>
<!-- example, elite yeti -->
<item type="14" index="300">
<spawn monster="20" count="30" duration="60" />
<!-- rules for use this spot (false: any user can attack, true: only owner & by rules) -->
<private active="true">
<party>true</party>
<guild>false</guild>
</private>
</item>
</monsterspawner>


aqui fica os código que eu pegue da source da Zteam

MonsterSpawner.cpp

PHP:
#include "stdafx.h"
#include "MonsterSpawner.h"
#include "GameMain.h"
#include "..\pugixml\pugixml.hpp"

MonsterSpawnerMng* MonsterSpawnerMng::m_Instance = NULL;

MonsterSpawnerMng::MonsterSpawnerMng() {
    m_WorkPool.clear();
    //m_ItemData.clear();
}

MonsterSpawnerMng::~MonsterSpawnerMng() {
    // lifetime instance...
}

void MonsterSpawnerMng::Load() {
    m_Loaded = false;
    Init();
    Read(gDirPath.GetNewPath(FILE_CUSTOM_MONSTERSPAWNER));
}

void MonsterSpawnerMng::Init() {
    m_ItemData.clear();
}

void MonsterSpawnerMng::Read(const char *File) {
    using namespace pugi;
    xml_document Document;
    xml_parse_result Result = Document.load_file(File);
    if (Result.status != status_ok) {
        MsgBox("[MonsterSpawnerMng] File %s not found!", File);
        return;
    }
    xml_node nodeMain = Document.child("monsterspawner");
    for (xml_node nodeIt = nodeMain.child("item"); nodeIt; nodeIt = nodeIt.next_sibling()) {
        MonsterSpawnerItemInfo newItem = { 0 };
        newItem.itemCategory = nodeIt.attribute("type").as_int(-1);
        newItem.itemIndex = nodeIt.attribute("index").as_int(-1);
        newItem.spawnMonsterId = nodeIt.child("spawn").attribute("monster").as_int(-1);
        newItem.spawnMonsterCount = nodeIt.child("spawn").attribute("count").as_int(-1);
        newItem.spawnDuration = nodeIt.child("spawn").attribute("duration").as_int(-1);
        newItem.isPrivate = nodeIt.child("private").attribute("active").as_bool();
        newItem.isPrivateParty = nodeIt.child("private").child("party").text().as_bool();
        newItem.isPrivateGuild = nodeIt.child("private").child("guild").text().as_bool();
        m_ItemData.push_back(newItem);
    }
    LogAddTD("[MonsterSpawnerMng] loaded %d node(s)", m_ItemData.size());
    m_Loaded = true;
}

void MonsterSpawnerMng::procRun() {

    for (size_t i = 0; i < m_WorkPool.size(); i++) {

        if (m_WorkPool[i].isEmpty()) {
            continue;
        }
        if (m_WorkPool[i].isExpired()) {
            LogAddTD("[MonsterSpawnerMng] [%s] spot duration is expired, slot cleared",
                m_WorkPool[i].ownerName.c_str());
            m_WorkPool[i].clearSlot();
        }
    }
}

void MonsterSpawnerMng::procRegen(short MonsterIndex) {
    gObj[MonsterIndex].X = gObj[MonsterIndex].StartX;
    gObj[MonsterIndex].Y = gObj[MonsterIndex].StartY;
    gObj[MonsterIndex].MTX = gObj[MonsterIndex].X;
    gObj[MonsterIndex].MTY = gObj[MonsterIndex].Y;
    gObj[MonsterIndex].m_ActState.Emotion = 1;
    gObj[MonsterIndex].m_ActState.EmotionCount = 1;
}

bool MonsterSpawnerMng::procCreate(short UserIndex, int ItemCode) {
    MonsterSpawnerItemInfo* tmpItemInfo = getItemInfo(ItemCode);
    if (tmpItemInfo == NULL) {
        return false;
    }
    int tmpSlotIndex = getEmptySlot();
    if (tmpSlotIndex == -1) {
        MonsterSpawnerWorkNode newNode;
        newNode.setSlot(UserIndex, tmpItemInfo);
        m_WorkPool.push_back(newNode);
    } else {
        m_WorkPool[tmpSlotIndex].setSlot(UserIndex, tmpItemInfo);
    }
    LogAddTD("[MonsterSpawnerMng] [%s][%s] spot has been created (monster: %d, count: %d, duration: %d, map: %d (%d:%d))",
        gObj[UserIndex].AccountID, gObj[UserIndex].Name, tmpItemInfo->spawnMonsterId, tmpItemInfo->spawnMonsterCount,
        tmpItemInfo->spawnDuration, gObj[UserIndex].MapNumber, gObj[UserIndex].X, gObj[UserIndex].Y);
    return true;
}

bool MonsterSpawnerMng::isPrivate(short UserIndex, short MonsterIndex) {
    LPOBJ tmpAttacker = &gObj[UserIndex];
    LPOBJ tmpMonster = &gObj[MonsterIndex];
    LPOBJ tmpOwner = NULL;
    MonsterSpawnerWorkNode* tmpNode = NULL;
    MonsterSpawnerItemInfo* tmpItem = NULL;

    for (size_t i = 0; i < m_WorkPool.size(); i++) { // select node

        if (m_WorkPool[i].isMonster(MonsterIndex)) {
            tmpNode = &m_WorkPool[i];
            break;
        }
    }
    if (tmpNode == NULL) { // node not founded, spot unblocked
        return false;
    }
    if (tmpNode->isOwner(tmpAttacker->Name)) { // owner
        return false;
    }
    tmpItem = getItemInfo(tmpNode->itemCode);
    if (tmpItem == NULL) { // rules for node not founded, spot unblocked
        return false;
    }
    if (!tmpItem->isPrivate) { // spot not privated by rules
        return false;
    }
    for (int i = OBJ_STARTUSERINDEX; i < OBJMAX; i++) { // select live owner
        if (gObj[i].Connected >= PLAYER_PLAYING) {
            if (tmpNode->isOwner(gObj[i].Name)) {
                tmpOwner = &gObj[i];
                break;
            }
        }
    }
    if (tmpOwner == NULL) { // spot have owner, but owner is offline, cant check rules - block by rules
        MsgOutput(UserIndex, "Monster is privated by %s", tmpNode->ownerName.c_str());
        return true;
    }
    if (tmpItem->isPrivateParty && tmpOwner->PartyNumber >= 0) { // spot is not privated for party members
        if (tmpOwner->PartyNumber == tmpAttacker->PartyNumber) {
            return false;
        }
    }
    if (tmpItem->isPrivateGuild && tmpOwner->GuildNumber > 0) { // spot is not privated for guild members
        if (tmpOwner->GuildNumber == tmpAttacker->GuildNumber) {
            return false;
        }
    }
    MsgOutput(UserIndex, "Monster is privated by %s", tmpNode->ownerName.c_str());
    return true;
}

bool MonsterSpawnerMng::isEventMonster(short MonsterIndex) {

    for (size_t i = 0; i < m_WorkPool.size(); i++) {

        if (m_WorkPool[i].isMonster(MonsterIndex)) {
            return true;
        }
    }
    return false;
}

bool MonsterSpawnerMng::isKeyItem(int ItemCode) {
    if (getItemInfo(ItemCode) != NULL) {
        return true;
    }
    return false;
}

int MonsterSpawnerMng::getEmptySlot() {

    for (size_t i = 0; i < m_WorkPool.size(); i++) {

        if (m_WorkPool[i].isEmpty()) {
            return i;
        }
    }
    return -1;
}

MonsterSpawnerItemInfo* MonsterSpawnerMng::getItemInfo(int ItemCode) {
    if (!m_Loaded) {
        return NULL;
    }

    for (size_t i = 0; i < m_ItemData.size(); i++) {

        if (ITEMGET(m_ItemData[i].itemCategory, m_ItemData[i].itemIndex) == ItemCode) {
            return &m_ItemData[i];
        }
    }
    return NULL;
}

MonsterSpawner.h



PHP:
#pragma once

// import
#include "user.h"

// data
struct MonsterSpawnerItemInfo {
    short itemIndex;
    short itemCategory;
    short spawnMonsterId;
    short spawnMonsterCount;
    short spawnDuration;
    bool isPrivate;
    bool isPrivateParty;
    bool isPrivateGuild;
};

struct MonsterSpawnerWorkNode { // maybe better use class & ptr instance...
    MonsterSpawnerWorkNode() {
        ownerName.reserve(MAX_ACCOUNT_LEN + 1);
        monsterPool.clear();
        itemCode = -1;
        tickEnd = 0;
    }
    void setSlot(short UserIndex, MonsterSpawnerItemInfo* itemInfo) {
        if (UserIndex < 0 || UserIndex > OBJMAX) {
            return;
        }
        LPOBJ tmpUser = &gObj[UserIndex];
        if (tmpUser == NULL) {
            return;
        }
        ownerName.assign(tmpUser->Name);
        itemCode = ITEMGET(itemInfo->itemCategory, itemInfo->itemIndex);
        tickEnd = GetTickCount() + (itemInfo->spawnDuration * 60 * 1000);
        setSpot(UserIndex, itemInfo);
    }
    void clearSlot() {
        ownerName.assign("");
        itemCode = -1;
        tickEnd = 0;
        clearSpot();
        monsterPool.clear();
    }
    void setSpot(short UserIndex, MonsterSpawnerItemInfo* itemInfo) {
        if (UserIndex < 0 || UserIndex > OBJMAX) {
            return;
        }
        LPOBJ tmpUser = &gObj[UserIndex];
        if (tmpUser == NULL) {
            return;
        }
        for (int i = 0; i < itemInfo->spawnMonsterCount; i++) {
            int tmpMonsterIndex = gObjAddMonster(tmpUser->MapNumber);
            if (tmpMonsterIndex < 0) {
                return;
            }
            gObj[tmpMonsterIndex].m_PosNum = -1;
            gObj[tmpMonsterIndex].X    = tmpUser->X + rand() % 2;
            gObj[tmpMonsterIndex].Y    = tmpUser->Y + rand() % 2;
            gObj[tmpMonsterIndex].MapNumber    = tmpUser->MapNumber;
            gObj[tmpMonsterIndex].TX = gObj[tmpMonsterIndex].X;
            gObj[tmpMonsterIndex].TY = gObj[tmpMonsterIndex].Y;
            gObj[tmpMonsterIndex].m_OldX = gObj[tmpMonsterIndex].X;
            gObj[tmpMonsterIndex].m_OldY = gObj[tmpMonsterIndex].Y;
            gObj[tmpMonsterIndex].StartX = gObj[tmpMonsterIndex].X;
            gObj[tmpMonsterIndex].StartY = gObj[tmpMonsterIndex].Y;
            gObj[tmpMonsterIndex].m_ActState.Emotion = 1;
            gObj[tmpMonsterIndex].m_ActState.EmotionCount = 15;
            gObj[tmpMonsterIndex].Dir = rand() % 8;
            gObjSetMonster(tmpMonsterIndex, itemInfo->spawnMonsterId);
            monsterPool.push_back(tmpMonsterIndex);
        }
    }
    void clearSpot() {

        for (size_t i = 0; i < monsterPool.size(); i++) {

            gObjViewportListProtocolDestroy(&gObj[monsterPool[i]]);
            gObjViewportClose(&gObj[monsterPool[i]]);
            gObjDel(monsterPool[i]);
            gObj[monsterPool[i]].Live = 0;
            gObj[monsterPool[i]].DieRegen = 1;
        }
    }
    bool isOwner(char* OwnerName) {
        if (ownerName.compare(OwnerName) == NULL) {
            return true;
        }
        return false;
    }
    bool isMonster(short MonsterIndex) {

        for (size_t i = 0; i < monsterPool.size(); i++) {

            if (monsterPool[i] == MonsterIndex) {
                return true;
            }
        }
        return false;
    }
    bool isEmpty() {
        if (isOwner("")) {
            return true;
        }
        return false;
    }
    bool isExpired() {
        if (GetTickCount() >= tickEnd) {
            return true;
        }
        return false;
    }
    std::string ownerName;
    std::vector<short> monsterPool;
    int itemCode;
    DWORD tickEnd;
};

// monster spawner by item drop impletation
class MonsterSpawnerMng {
public:
    MonsterSpawnerMng();
    ~MonsterSpawnerMng();

    void Load();
    void Init();
    void Read(const char* File);

    void procRun();
    void procRegen(short MonsterIndex);
    bool procCreate(short UserIndex, int ItemCode);
    
    bool isPrivate(short UserIndex, short MonsterIndex);
    bool isEventMonster(short MonsterIndex);
    bool isKeyItem(int ItemCode);
    int getEmptySlot();
    MonsterSpawnerItemInfo* getItemInfo(int ItemCode);

    // singleton
    static MonsterSpawnerMng* getInstance() {
        if (m_Instance == NULL) {
            m_Instance = new MonsterSpawnerMng();
        }
        return m_Instance;
    }

private:
    static MonsterSpawnerMng* m_Instance;
    std::vector<MonsterSpawnerWorkNode> m_WorkPool;
    std::vector<MonsterSpawnerItemInfo> m_ItemData;

private:
    bool m_Loaded;
};
 
Back
Top