• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ /atrr skills

silveralol

Advanced OT User
Joined
Mar 16, 2010
Messages
1,480
Solutions
9
Reaction score
211
hello folks, as the title says I'm requesting a function in c++ that set the spawn positions, I need it to handle with some world changes ...
to be possible to create monsters by scripts and set their spawn positions to them spawn normal as the others monsters...
also I need a function that set skills in items...
exemple:
/attr skillname, value
I have some code for exemple..
Lua:
function onSay(player, words, param)

    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local t = param:split(" ", 1)
    local attr = t[1]
    local value = (t[2])

    local position = player:getPosition()
    position:getNextPosition(player:getDirection())

    local tile = position:getTile()
    if not tile then
        player:sendCancelMessage("Object not found.")
        return false
    end

    local thing = tile:getTopVisibleThing(player)
    if not thing then
        player:sendCancelMessage("Thing not found.")
        return false
    end

    if thing:isItem() then
        if attr == "skillfist" then
            thing:setAttribute('skillfist', value)
        else
            player:sendCancelMessage("Bad Attribute.")
            return true
        end
    end

    position:sendMagicEffect(CONST_ME_MAGIC_RED)
    return false
end
 
Last edited by a moderator:
Solution
Okay I didn't run the check spawn procedure

Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
    // monster:setSpawnPosition()
    Monster* monster = getUserdata<Monster>(L, 1);
    if (!monster) {
        lua_pushnil(L);
        return 1;
    }

    const Position& pos = monster->getPosition();
    monster->setMasterPos(pos);

    g_game.map.spawns.getSpawnList().emplace_front(pos, 5);
    Spawn& spawn = g_game.map.spawns.getSpawnList().front();
    spawn.addMonster(monster->mType->name, pos, DIRECTION_NORTH, 60000);
    spawn.startSpawnCheck();

    pushBoolean(L, true);
    return 1;
}

Code:
    local monster = Game.createMonster('Dwarf', Position(95, 127, 7))
    monster:setSpawnPosition(Position(95, 130...
I do some code in c++
Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
    // monster:setSpawnPosition()
    Monster* monster = getUserdata<Monster>(L, 1);
    if (!monster) {
        lua_pushnil(L);
        return 1;
    }

    const Position& pos = monster->getPosition();
    monster->setMasterPos(pos);
   
    uint32_t spawnId = spawnMap.size() + 1; // error here
    spawnedMap.insert(spawned_pair(spawnId, monster)); // error here
    spawnMap[spawnId].lastSpawn = OTSYS_TIME(); // error here
    pushBoolean(L, true);
    return 1;
}
ofc don't work... I need insert this monsters to the table of spawnedMap..
so I try include spawn.h in luascript.cpp get some errors with variables as the spawnedMap
then I try put in public class the declarations of spawn.h
Code:
       //map of the spawned creatures
        typedef std::multimap<uint32_t, Monster*> SpawnedMap;
        typedef SpawnedMap::value_type spawned_pair;
        SpawnedMap spawnedMap;
but still
1 IntelliSense: identifier "spawnMap" is undefined c:\forgottenserver\src\luascript.cpp 9685 21 theforgottenserver

2 IntelliSense: identifier "spawnedMap" is undefined c:\forgottenserver\src\luascript.cpp 9686 2 theforgottenserver
3 IntelliSense: identifier "spawned_pair" is undefined c:\forgottenserver\src\luascript.cpp 9686 20 theforgottenserver
 
Last edited:
add new geter to Spawns class

Code:
        std::forward_list<Spawn> getSpawnList()
        {
            return spawnList;
        }

then you can get into spawnlist in luascript

Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
...
    g_game.map.spawns.getSpawnList().emplace_front(POSITION, RADIUS);
    Spawn& spawn = g_game.map.spawns.getSpawnList().front();
    spawn.addMonster(MONSTER_NAME_AS_STRING, POSITION, DIRECTION, INTERVAL);
...
 
yes, it could be done in this way, but my point, I want it on c++ also to be possible with handle with Game.loadMap(), also this globalevent could make my server heavy, I mean, waste RAM... so, if is possible do in c++ then someone should do it in c++
thank you very much
technically you can just use game.loadmap and load in everything you want. as far as I know, it should load spawns in as well.
 
technically you can just use game.loadmap and load in everything you want. as far as I know, it should load spawns in as well.
as @Mkalo said, "no" it doens't load any spawn... is because of that missing that I want the function :oops:

edit:
add new geter to Spawns class

Code:
        std::forward_list<Spawn> getSpawnList()
        {
            return spawnList;
        }

then you can get into spawnlist in luascript

Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
...
    g_game.map.spawns.getSpawnList().emplace_front(POSITION, RADIUS);
    Spawn& spawn = g_game.map.spawns.getSpawnList().front();
    spawn.addMonster(MONSTER_NAME_AS_STRING, POSITION, DIRECTION, INTERVAL);
...
could you explain where I can paste this code ? I'm dying here tired haha
 
Last edited:
spawn.h file, edit class Spawns
Code:
class Spawns
{
    public:
        static bool isInZone(const Position& centerPos, int32_t radius, const Position& pos);

        bool loadFromXml(const std::string& filename);
        void startup();
        void clear();

        bool isStarted() const {
            return started;
        }

        //here
        std::forward_list<Spawn> getSpawnList()
        {
            return spawnList;
        }
        //end

    private:
        std::forward_list<Npc*> npcList;
        std::forward_list<Spawn> spawnList;
        std::string filename;
        bool loaded = false;
        bool started = false;
};

Then you can edit the spawnlist from another objects (for example luascripts)

Your code:
Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
    // monster:setSpawnPosition()
    Monster* monster = getUserdata<Monster>(L, 1);
    if (!monster) {
        lua_pushnil(L);
        return 1;
    }

    const Position& pos = monster->getPosition();
    monster->setMasterPos(pos);
   
    uint32_t spawnId = spawnMap.size() + 1; // error here
    spawnedMap.insert(spawned_pair(spawnId, monster)); // error here
    spawnMap[spawnId].lastSpawn = OTSYS_TIME(); // error here
    pushBoolean(L, true);
    return 1;
}

should be fine with this
Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
    // monster:setSpawnPosition()
    Monster* monster = getUserdata<Monster>(L, 1);
    if (!monster) {
        lua_pushnil(L);
        return 1;
    }

    const Position& pos = monster->getPosition();
    monster->setMasterPos(pos);
   
    g_game.map.spawns.getSpawnList().emplace_front(pos, 5);
    Spawn& spawn = g_game.map.spawns.getSpawnList().front();
    spawn.addMonster(monster->mType->name, pos, 1, 60);

    pushBoolean(L, true);
    return 1;
}

Should be something like this. Some errors might occur, I have no possibility to test it now.
 
@pasiak12 have an error strange
Code:
c:\forgottenserver\src\spawn.h(107) : see reference to function template instantiation 'std::forward_list<Spawn,std::allocator<_Ty>>::forward_list(const std::forward_list<_Ty,std::allocator<_Ty>> &)' being compiled
1>          with
1>          [
1>              _Ty=Spawn
1>          ]
1>          c:\forgottenserver\src\spawn.h(102) : see reference to class template instantiation 'std::forward_list<Spawn,std::allocator<_Ty>>' being compiled
1>          with
1>          [
1>              _Ty=Spawn
1>          ]
I try move the declaration of spawnList from private to public, but get the same error
the error:
Error 6 error C2280: 'Spawn::Spawn(const Spawn &)' : attempting to reference a deleted function (..\src\configmanager.cpp) C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0 600 1 theforgottenserver
 
a yeah, shoulda pass the reference

this should compile
Code:
class Spawns
{
    public:
        static bool isInZone(const Position& centerPos, int32_t radius, const Position& pos);

        bool loadFromXml(const std::string& filename);
        void startup();
        void clear();

        bool isStarted() const {
            return started;
        }

        //here
        std::forward_list<Spawn>& getSpawnList()
        {
            return spawnList;
        }
        //end

    private:
        std::forward_list<Npc*> npcList;
        std::forward_list<Spawn> spawnList;
        std::string filename;
        bool loaded = false;
        bool started = false;
};
 
@pasiak12 it compile pretty well, thank you
but I get an error while testing with lua script
then, I use a custom action script to do the test
Code:
    for x = 33295, 33300 do
        for y = 31400, 31407 do
            if math.random(4) >= 3 then
                local monster = Game.createMonster('fury', Position(x,y, 12))
                if monster then
                    monster:setSpawnPosition()
                end
            end
        end
    end
but attempt to call method 'setSpawnPosition' (a nil value)
well, my function is named correctly
c++
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)

and luascript.h

static int luaMonsterSetSpawnPosition(lua_State* L);
what is wrong ?
 
@pasiak12 it compile pretty well, thank you
but I get an error while testing with lua script
then, I use a custom action script to do the test
Code:
    for x = 33295, 33300 do
        for y = 31400, 31407 do
            if math.random(4) >= 3 then
                local monster = Game.createMonster('fury', Position(x,y, 12))
                if monster then
                    monster:setSpawnPosition()
                end
            end
        end
    end
but attempt to call method 'setSpawnPosition' (a nil value)
well, my function is named correctly
c++
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)

and luascript.h

static int luaMonsterSetSpawnPosition(lua_State* L);
what is wrong ?
did you do
C++:
registerMethod("Monster", "setSpawnPosition", LuaScriptInterface::luaMonsterSetSpawnPosition);
 
sure...
@Xeraphus thanks for the quick fix about the line missing
@pasiak12 compiled, tested and the monsters don't spawn again :/
we can start the debug commenting what each line do, so can be possible find the soluction :rolleyes:
 
Last edited:
Okay I didn't run the check spawn procedure

Code:
int LuaScriptInterface::luaMonsterSetSpawnPosition(lua_State* L)
{
    // monster:setSpawnPosition()
    Monster* monster = getUserdata<Monster>(L, 1);
    if (!monster) {
        lua_pushnil(L);
        return 1;
    }

    const Position& pos = monster->getPosition();
    monster->setMasterPos(pos);

    g_game.map.spawns.getSpawnList().emplace_front(pos, 5);
    Spawn& spawn = g_game.map.spawns.getSpawnList().front();
    spawn.addMonster(monster->mType->name, pos, DIRECTION_NORTH, 60000);
    spawn.startSpawnCheck();

    pushBoolean(L, true);
    return 1;
}

Code:
    local monster = Game.createMonster('Dwarf', Position(95, 127, 7))
    monster:setSpawnPosition(Position(95, 130, 7))

worked for me

//I tested it only on newly created monsters, the problems may occur if you try use this on already existing monster on map
 
Last edited:
Solution
You don't need C++ for this, and it's ugly.

Code:
function Game.executeSpawn(spawnId)
    if not StoreSpawn then
        return false
    end

    if not CreatureSpawn then
        CreatureSpawn = {}
    end

    local spawn = StoreSpawn[spawnId]
    if spawn then
        local monster = Game.createMonster(spawn[1], spawn[2], true, true)
        if not monster then
            return addEvent(executeSpawn, spawn[3], spawnId) -- retry later in spawntime miliseconds
        end

        CreatureSpawn[monster:getId()] = spawnId
        monster:registerEvent("SpawnDeath")
        return monster:getId()
    end
end

function Game.createSpawn(name, spawntime, position)
    if not StoreSpawn then
        StoreSpawn = {}
        lastSpawnId = 0
    end

    local mType = MonsterType(name)
    if not mType then
        return false
    end

    lastSpawnId = lastSpawnId + 1

    local spawnId = lastSpawnId
    StoreSpawn[spawnId] = {name, position, spawntime}

    local spawnEvent = Game.executeSpawn(spawnId)
    StoreSpawn[spawnId][4] = spawnEvent

    return spawnId
end

function Game.removeSpawn(spawnId)
    if not StoreSpawn then
        return false
    end

    local spawn = StoreSpawn[spawnId]
    if not spawn then
        return false
    end

    if spawn[4] then
        local monster = Monster(spawn[4])
        if monster then
            monster:remove()
        else
            stopEvent(spawn[4])
        end
    end

    StoreSpawn[spawnId] = nil
    return true
end

SpawnDeath:
Code:
function onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    if not CreatureSpawn or not StoreSpawn then
        return true
    end

    local creatureId = creature:getId()
    local spawnId = CreatureSpawn[creatureId]
    CreatureSpawn[creatureId] = nil

    local spawn = StoreSpawn[spawnId]

    if not spawn then
        return true
    end

    spawn[4] = addEvent(Game.executeSpawn, spawn[3], spawnId)
    return true
end
 
Back
Top