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

TFS 0.X 0.4 - Player in PZ detection

Snavy

Bakasta
Senator
Joined
Apr 1, 2012
Messages
1,249
Solutions
71
Reaction score
628
Location
Hell
GitHub
idontreallywolf
Is it possible to detect if a player is inside PZ? I am trying to make a script in movements (if that's even correct) in order to detect if players stepped in pz. I got stuck because in movements you have to determine itemid, actionid or uniqueid for specific tiles. Is there a way to make this work for all tiles?

TFS: 0.4
OTS V: 8.6
 
Last edited:
Solution
Different 0.4 version :D
just copy this part
C++:
       //remove summons
       for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
       {
           (*it)->setAttackedCreature(NULL);
           (*it)->setMaster(NULL);
           (*it)->unRef();
           g_game.removeCreature(*it);
       }
       summons.clear();
       //or this to kill summoners
       //destroySummons()
Is it possible to detect if a player is inside PZ? I am trying to make a script in movements (if that's even correct) in order to detect if players stepped in pz. I got stuck because in movements you have to determine itemid, actionid or uniqueid for specific tiles. Is there a way to make this work for all tiles?
This is related to Tile::__queryAdd(...), unless you're thinking of adding action id to all of the tiles, I'd edit the source
 
This is related to Tile::__queryAdd(...), unless you're thinking of adding action id to all of the tiles, I'd edit the source

is this the part i have to edit ?
C++:
if(const Monster* monster = creature->getMonster())
                {
                        if(hasFlag(TILESTATE_PROTECTIONZONE))
                                return RET_NOTPOSSIBLE;
 
It's not that part, as you can see the snippet you posted determines wether or not it's a Monster (in this case it is)

Post the full function and tell us what you want to acheive
 
It's not that part, as you can see the snippet you posted determines wether or not it's a Monster (in this case it is)

Post the full function and tell us what you want to acheive

well, I wanted to remove summons whenever a player stepped into a PZ

C++:
ReturnValue Tile::__queryAdd(int32_t, const Thing* thing, uint32_t,
   uint32_t flags) const
{
   const CreatureVector* creatures = getCreatures();
   const TileItemVector* items = getItemList();
   if(const Creature* creature = thing->getCreature())
   {
       if(hasBitSet(FLAG_NOLIMIT, flags))
           return RET_NOERROR;

       if(hasBitSet(FLAG_PATHFINDING, flags))
       {
           if(floorChange() || positionChange())
               return RET_NOTPOSSIBLE;
       }

       if(!ground)
           return RET_NOTPOSSIBLE;

       if(const Monster* monster = creature->getMonster())
       {
           if(hasFlag(TILESTATE_PROTECTIONZONE))
               return RET_NOTPOSSIBLE;

           if(floorChange() || positionChange())
               return RET_NOTPOSSIBLE;

           if(monster->canPushCreatures() && !monster->isSummon())
           {
               if(creatures && !creatures->empty())
               {
                   Creature* tmp = NULL;
                   for(uint32_t i = 0; i < creatures->size(); ++i)
                   {
                       tmp = creatures->at(i);
                       if(creature->canWalkthrough(tmp))
                           continue;

                       if(!tmp->getMonster() || !tmp->isPushable() || tmp->isPlayerSummon())
                           return RET_NOTPOSSIBLE;
                   }
               }
           }
           else if(creatures && !creatures->empty())
           {
               for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
               {
                   if(!creature->canWalkthrough(*cit))
                       return RET_NOTENOUGHROOM; //NOTPOSSIBLE
               }
           }

           if(hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))
               return RET_NOTPOSSIBLE;

           if(hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH))
               return RET_NOTPOSSIBLE;

           if((hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH)))
               && (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))))
               return RET_NOTPOSSIBLE;

           if(!items) // Do not seek for fields if there are no items
               return RET_NOERROR;

           MagicField* field = getFieldItem();
           if(!field)
               return RET_NOERROR;

           if(field->isBlocking(creature))
               return RET_NOTPOSSIBLE;

           CombatType_t combatType = field->getCombatType();
           //There is 3 options for a monster to enter a magic field
           //1) Monster is immune
           if(monster->isImmune(combatType))
               return RET_NOERROR;

           //1) Monster is "strong" enough to handle the damage
           //2) Monster is already afflicated by this type of condition
           if(!hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags))
               return RET_NOTPOSSIBLE;

           return !monster->hasCondition(Combat::DamageToConditionType(combatType), -1, false)
               && !monster->canPushItems() ? RET_NOTPOSSIBLE : RET_NOERROR;
       }

       if(const Player* player = creature->getPlayer())
       {
           if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
           {
               for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
               {
                   if(!creature->canWalkthrough(*cit))
                       return RET_NOTENOUGHROOM; //NOTPOSSIBLE
               }
           }

           if(!player->getParent() && hasFlag(TILESTATE_NOLOGOUT)) //player is trying to login to a "no logout" tile
               return RET_NOTPOSSIBLE;

           if(player->isPzLocked() && !player->getTile()->hasFlag(TILESTATE_HARDCOREZONE) && hasFlag(TILESTATE_HARDCOREZONE)) //player is trying to enter a pvp zone while being pz-locked
               return RET_PLAYERISPZLOCKEDENTERPVPZONE;

           if(player->isPzLocked() && player->getTile()->hasFlag(TILESTATE_HARDCOREZONE) && !hasFlag(TILESTATE_HARDCOREZONE)) //player is trying to leave a pvp zone while being pz-locked
               return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;

           if(hasFlag(TILESTATE_OPTIONALZONE) && player->isPzLocked())
               return RET_PLAYERISPZLOCKED;

           if(hasFlag(TILESTATE_PROTECTIONZONE) && player->isPzLocked())
               return RET_PLAYERISPZLOCKED;
       }
       else if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
       {
           for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
           {
               if(!creature->canWalkthrough(*cit))
                   return RET_NOTENOUGHROOM; //NOTPOSSIBLE
           }
       }

       if(items)
       {
           MagicField* field = getFieldItem();
           if(field && field->isBlocking(creature))
               return RET_NOTPOSSIBLE;

           if(hasBitSet(FLAG_IGNOREBLOCKITEM, flags)) //if the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
           {
               //FLAG_IGNOREBLOCKITEM is set
               if(ground)
               {
                   const ItemType& iType = Item::items[ground->getID()];
                   if(ground->isBlocking(creature) && (!iType.moveable || (ground->isLoadedFromMap() &&
                       (ground->getUniqueId() || (ground->getActionId() && ground->getContainer())))))
                       return RET_NOTPOSSIBLE;
               }

               if(const TileItemVector* items = getItemList())
               {
                   for(ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
                   {
                       const ItemType& iType = Item::items[(*it)->getID()];
                       if((*it)->isBlocking(creature) && (!iType.moveable || ((*it)->isLoadedFromMap() &&
                           ((*it)->getUniqueId() || ((*it)->getActionId() && (*it)->getContainer())))))
                           return RET_NOTPOSSIBLE;
                   }
               }
           }
           else if(hasFlag(TILESTATE_BLOCKSOLID))
               return RET_NOTPOSSIBLE;
       }
   }
   else if(const Item* item = thing->getItem())
   {
#ifdef __DEBUG__
       if(thing->getParent() == NULL && !hasBitSet(FLAG_NOLIMIT, flags))
           std::clog << "[Notice - Tile::__queryAdd] thing->getParent() == NULL" << std::endl;

#endif
       if(items && items->size() >= 0xFFFF)
           return RET_NOTPOSSIBLE;

       if(hasBitSet(FLAG_NOLIMIT, flags))
           return RET_NOERROR;

       bool itemIsHangable = item->isHangable();
       if(!ground && !itemIsHangable)
           return RET_NOTPOSSIBLE;

       if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
       {
           for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
           {
               if(!(*cit)->isGhost() && item->isBlocking(*cit))
                   return RET_NOTENOUGHROOM; //NOTPOSSIBLE
           }
       }

       const uint32_t itemLimit = g_config.getNumber(
               hasFlag(TILESTATE_PROTECTIONZONE) ? ConfigManager::PROTECTION_TILE_LIMIT : ConfigManager::TILE_LIMIT);
       if(itemLimit && getThingCount() > itemLimit)
           return RET_TILEISFULL;

       bool hasHangable = false, supportHangable = false;
       if(items)
       {
           Thing* iThing = NULL;
           for(uint32_t i = 0; i < getThingCount(); ++i)
           {
               iThing = __getThing(i);
               if(const Item* iItem = iThing->getItem())
               {
                   const ItemType& iType = Item::items[iItem->getID()];
                   if(iType.isHangable)
                       hasHangable = true;

                   if(iType.isHorizontal || iType.isVertical)
                       supportHangable = true;

                   if(itemIsHangable && (iType.isHorizontal || iType.isVertical))
                       continue;
                   else if(iItem->isBlocking(NULL))
                   {
                       if(!item->isPickupable())
                           return RET_NOTPOSSIBLE;

                       if(iType.allowPickupable)
                           continue;

                       if(!iType.hasHeight || iType.pickupable || iType.isBed())
                           return RET_NOTPOSSIBLE;
                   }
               }
           }
       }

       if(itemIsHangable && hasHangable && supportHangable)
           return RET_NEEDEXCHANGE;
   }

   return RET_NOERROR;
}
 
I haven't been able to test it, but try change line 103 and 104 with:
C++:
if(!player->getTile()->hasFlag(TILESTATE_HARDCOREZONE) && hasFlag(TILESTATE_HARDCOREZONE)) {   
    //player is trying to enter a pvp zone while being pz-locked
    if (player->isPzLocked()) {
        return RET_PLAYERISPZLOCKEDENTERPVPZONE;
    } else {
        // Remove summons
        if (player->getMaster()) {
            for(std::list<Creature*>::iterator it = creature->summons.begin(); it != creature->summons.end(); ++it) {
                removeCreature(*it);   
            }           
        }
    }
}
 
in player.cpp
replace this function
C++:
void Player::onChangeZone(ZoneType_t zone)
{
   if(zone == ZONE_PROTECTION && !hasFlag(PlayerFlag_IgnoreProtectionZone))
   {
       if(attackedCreature)
       {
           setAttackedCreature(NULL);
           onTargetDisappear(false);
       }
       //remove summons
       for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
       {
           (*it)->setAttackedCreature(NULL);
           (*it)->setMaster(NULL);
           (*it)->unRef();
           g_game.removeCreature(*it);
       }
       summons.clear();
       //or this to kill summoners
       //destroySummons()
       
       if(g_config.getBool(ConfigManager::UNMOUNT_PLAYER_IN_PZ))
           dismount(true);
   }

   g_game.updateCreatureWalkthrough(this);
   sendIcons();
}
 
in player.cpp
replace this function
C++:
void Player::onChangeZone(ZoneType_t zone)
{
   if(zone == ZONE_PROTECTION && !hasFlag(PlayerFlag_IgnoreProtectionZone))
   {
       if(attackedCreature)
       {
           setAttackedCreature(NULL);
           onTargetDisappear(false);
       }
       //remove summons
       for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
       {
           (*it)->setAttackedCreature(NULL);
           (*it)->setMaster(NULL);
           (*it)->unRef();
           g_game.removeCreature(*it);
       }
       summons.clear();
       //or this to kill summoners
       //destroySummons()
     
       if(g_config.getBool(ConfigManager::UNMOUNT_PLAYER_IN_PZ))
           dismount(true);
   }

   g_game.updateCreatureWalkthrough(this);
   sendIcons();
}

Uhm, i have faced this error ( btw, Iam using TFS 0.4 on 8.6 datapack ):
Code:
player.cpp: In member function ‘virtual void Player::onChangeZone(ZoneType_t)’:
player.cpp:1406:35: error: ‘onTargetDisappear’ was not declared in this scope
            onTargetDisappear(false);
                                   ^
player.cpp:1420:28: error: ‘UNMOUNT_PLAYER_IN_PZ’ is not a member of ‘ConfigManager’
        if(g_config.getBool(ConfigManager::UNMOUNT_PLAYER_IN_PZ))
                            ^
player.cpp:1421:25: error: ‘dismount’ was not declared in this scope
            dismount(true);
                         ^
player.cpp:1424:11: error: ‘class Game’ has no member named ‘updateCreatureWalkthrough’
    g_game.updateCreatureWalkthrough(this);
           ^
Makefile:541: recipe for target 'player.o' failed
make[1]: *** [player.o] Error 1
make[1]: Leaving directory '/home/plebinator/Downloads/trunk.r3777'
Makefile:396: recipe for target 'all' failed
make: *** [all] Error 2
 
Different 0.4 version :D
just copy this part
C++:
       //remove summons
       for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
       {
           (*it)->setAttackedCreature(NULL);
           (*it)->setMaster(NULL);
           (*it)->unRef();
           g_game.removeCreature(*it);
       }
       summons.clear();
       //or this to kill summoners
       //destroySummons()
 
Solution
Back
Top