• 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!

Creature Stacking

Flatlander

Species Developer
Joined
Feb 17, 2009
Messages
2,461
Solutions
3
Reaction score
1,356
Location
Texas
Here is a first rough draft of "Creature Stacking" we are making this for many reasons... one of which is so small monsters can "swarm" you.

Here is Draft 2 (Works a little better now)
 
Last edited:
That looks really cool :)
 
What changes in TFS are required to make monsters stack?

None, not one change is needed in TFS for this.

<flag walkable="1"> in monsters.xml makes them walkable, then in otclient you need adjustments to monsters who stack up so their center point is adjusted.

My version still has a few issues, the monsters aren't drawn in the right order, and they aren't drawn in exactly the right places yet, but I like where it is going.
 
None, not one change is needed in TFS for this.

<flag walkable="1"> in monsters.xml makes them walkable, then in otclient you need adjustments to monsters who stack up so their center point is adjusted.

My version still has a few issues, the monsters aren't drawn in the right order, and they aren't drawn in exactly the right places yet, but I like where it is going.

Hmmm...

[Warning - Monsters::loadMonster] Unknown flag attribute: walkable. data/monster/Animals/rat.xml

What I'm doing wrong? :S

Code:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Rat" nameDescription="a rat" race="blood" experience="5" speed="134" manacost="200">
        <health now="20" max="20"/>
        <look type="21" corpse="5964"/>
        <targetchange interval="2000" chance="0"/>
        <strategy attack="100" defense="0"/>
        <flags>
                <flag summonable="1"/>
                <flag attackable="1"/>
                <flag hostile="1"/>
                <flag illusionable="1"/>
                <flag convinceable="1"/>
                <flag pushable="1"/>
                <flag canpushitems="0"/>
                <flag canpushcreatures="0"/>
                <flag targetdistance="1"/>
                <flag staticattack="90"/>
                <flag runonhealth="5"/>
                <flag walkable="1"/>
        </flags>
        <attacks>
                <attack name="melee" interval="2000" skill="6" attack="9"/>
        </attacks>
        <defenses armor="1" defense="2"/>
        <elements>
                <element earthPercent="25"/>
                <element holyPercent="10"/>
                <element icePercent="-10"/>
                <element deathPercent="-10"/>
        </elements>
        <voices interval="2000" chance="9">
                <voice sentence="Meep!"/>
        </voices>
        <loot>
                <item id="2696" chance="3990" /><!-- cheese -->
        </loot>
</monster>

#EDIT#

https://github.com/otland/forgottenserver/blob/master/src/monsters.cpp#L840#L876
 
Last edited:
Hmmm...

[Warning - Monsters::loadMonster] Unknown flag attribute: walkable. data/monster/Animals/rat.xml

What I'm doing wrong? :S

Code:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Rat" nameDescription="a rat" race="blood" experience="5" speed="134" manacost="200">
        <health now="20" max="20"/>
        <look type="21" corpse="5964"/>
        <targetchange interval="2000" chance="0"/>
        <strategy attack="100" defense="0"/>
        <flags>
                <flag summonable="1"/>
                <flag attackable="1"/>
                <flag hostile="1"/>
                <flag illusionable="1"/>
                <flag convinceable="1"/>
                <flag pushable="1"/>
                <flag canpushitems="0"/>
                <flag canpushcreatures="0"/>
                <flag targetdistance="1"/>
                <flag staticattack="90"/>
                <flag runonhealth="5"/>
                <flag walkable="1"/>
        </flags>
        <attacks>
                <attack name="melee" interval="2000" skill="6" attack="9"/>
        </attacks>
        <defenses armor="1" defense="2"/>
        <elements>
                <element earthPercent="25"/>
                <element holyPercent="10"/>
                <element icePercent="-10"/>
                <element deathPercent="-10"/>
        </elements>
        <voices interval="2000" chance="9">
                <voice sentence="Meep!"/>
        </voices>
        <loot>
                <item id="2696" chance="3990" /><!-- cheese -->
        </loot>
</monster>

#EDIT#

https://github.com/otland/forgottenserver/blob/master/src/monsters.cpp#L840#L876

Sadly, you personally are doing nothing wrong, other than using TFS 1.0

I have some experience with TFS 1.0, and from my experience I have learned that, it is missing a TON of features that are found in TFS 3.6 or 4.0.

If you want walkable to be a flag for monsters submit the request on GITHUB. and I'm sure they can easily add this feature in.
BTW my currently list is a bit bigger than the one TFS 1.0 has:

Code:
    else if(!xmlStrcmp(p->name, (const xmlChar*)"flags"))
     {
       for(xmlNodePtr tmpNode = p->children; tmpNode; tmpNode = tmpNode->next)
       {
         if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"flag"))
         {
           if(readXMLString(tmpNode, "summonable", strValue))
             mType->isSummonable = booleanString(strValue);

           if(readXMLString(tmpNode, "attackable", strValue))
             mType->isAttackable = booleanString(strValue);

           if(readXMLString(tmpNode, "hostile", strValue))
             mType->isHostile = booleanString(strValue);

           if(readXMLString(tmpNode, "illusionable", strValue))
             mType->isIllusionable = booleanString(strValue);

           if(readXMLString(tmpNode, "convinceable", strValue))
             mType->isConvinceable = booleanString(strValue);

           if(readXMLString(tmpNode, "pushable", strValue))
             mType->pushable = booleanString(strValue);

           if(readXMLString(tmpNode, "canpushitems", strValue))
             mType->canPushItems = booleanString(strValue);
            
           if(readXMLString(tmpNode, "canclimbitems", strValue))
             mType->canClimbItems = booleanString(strValue);

           if(readXMLString(tmpNode, "canghostdoors", strValue))
             mType->canGhostDoors = booleanString(strValue);

           if(readXMLString(tmpNode, "canfly", strValue))
             mType->canFly = booleanString(strValue);
            
           if(readXMLString(tmpNode, "canghostwalls", strValue))
             mType->canGhostWalls = booleanString(strValue);

           if(readXMLString(tmpNode, "canusestairs", strValue))
             mType->canUseStairs = booleanString(strValue);
            
           if(readXMLString(tmpNode, "canpushcreatures", strValue))
             mType->canPushCreatures = booleanString(strValue);

           if(readXMLString(tmpNode, "hidename", strValue))
             mType->hideName = booleanString(strValue);

           if(readXMLString(tmpNode, "hidehealth", strValue))
             mType->hideHealth = booleanString(strValue);

           if(readXMLInteger(tmpNode, "lootmessage", intValue))
             mType->lootMessage = (LootMessage_t)intValue;

           if(readXMLString(tmpNode, "alwaysactive", strValue))
             mType->alwaysactive = booleanString(strValue);

           if(readXMLString(tmpNode, "targetupstairs", strValue))
             mType->targetUpstairs = booleanString(strValue);
            
           if(readXMLInteger(tmpNode, "staticattack", intValue))
           {
             if(intValue < 0 || intValue > 100)
             {
               SHOW_XML_WARNING("staticattack lower than 0 or greater than 100");
               intValue = 0;
             }

             mType->staticAttackChance = intValue;
           }

           if(readXMLInteger(tmpNode, "lightlevel", intValue))
             mType->lightLevel = intValue;

           if(readXMLInteger(tmpNode, "lightcolor", intValue))
             mType->lightColor = intValue;

           if(readXMLInteger(tmpNode, "targetdistance", intValue))
           {
             if(intValue > Map::maxViewportX)
               SHOW_XML_WARNING("targetdistance greater than maxViewportX");

             mType->targetDistance = std::max(1, intValue);
           }

           if(readXMLInteger(tmpNode, "runonhealth", intValue))
             mType->runAwayHealth = intValue;

           if(readXMLString(tmpNode, "viewrange", strValue))
             mType->viewRange = strValue;
            
           if(readXMLString(tmpNode, "lureable", strValue))
             mType->isLureable = booleanString(strValue);

           if(readXMLString(tmpNode, "walkable", strValue))
             mType->isWalkable = booleanString(strValue);

           if(readXMLString(tmpNode, "skull", strValue))
             mType->skull = getSkulls(strValue);

           if(readXMLString(tmpNode, "shield", strValue))
             mType->partyShield = getPShields(strValue);

           if(readXMLString(tmpNode, "emblem", strValue))
             mType->guildEmblem = getEmblems(strValue);

           if(readXMLString(tmpNode, "eliminable", strValue))
             mType->eliminable = booleanString(strValue);
         }
       }
 
Back
Top