1 /*
2  *  Copyright (C) 2011-2016  OpenDungeons Team
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "creatureaction/CreatureActionClaimWallTile.h"
19 
20 #include "entities/Creature.h"
21 #include "entities/Tile.h"
22 #include "gamemap/GameMap.h"
23 #include "gamemap/Pathfinding.h"
24 #include "utils/Helper.h"
25 #include "utils/LogManager.h"
26 
CreatureActionClaimWallTile(Creature & creature,Tile & tileClaim)27 CreatureActionClaimWallTile::CreatureActionClaimWallTile(Creature& creature, Tile& tileClaim) :
28     CreatureAction(creature),
29     mTileClaim(tileClaim)
30 {
31     mTileClaim.addWorkerClaiming(mCreature);
32 }
33 
~CreatureActionClaimWallTile()34 CreatureActionClaimWallTile::~CreatureActionClaimWallTile()
35 {
36     mTileClaim.removeWorkerClaiming(mCreature);
37 }
38 
action()39 std::function<bool()> CreatureActionClaimWallTile::action()
40 {
41     return std::bind(&CreatureActionClaimWallTile::handleClaimWallTile,
42         std::ref(mCreature), std::ref(mTileClaim));
43 }
44 
handleClaimWallTile(Creature & creature,Tile & tileClaim)45 bool CreatureActionClaimWallTile::handleClaimWallTile(Creature& creature, Tile& tileClaim)
46 {
47     Tile* myTile = creature.getPositionTile();
48     if (myTile == nullptr)
49     {
50         OD_LOG_ERR("creature=" + creature.getName() + ", pos=" + Helper::toString(creature.getPosition()));
51         creature.popAction();
52         return false;
53     }
54 
55     // We check if the tile is still claimable
56     if(!tileClaim.isWallClaimable(creature.getSeat()))
57     {
58         creature.popAction();
59         return true;
60     }
61 
62     // We check if we are on a claimed tile next to the tile to claim
63     Tile* tileDest = nullptr;
64     float distBest = -1;
65     for(Tile* tile : tileClaim.getAllNeighbors())
66     {
67         // We look for the closest allowed tile
68         if(tile->isFullTile())
69             continue;
70         if(!creature.getGameMap()->pathExists(&creature, myTile, tile))
71             continue;
72         float dist = Pathfinding::squaredDistanceTile(*myTile, *tile);
73         if((distBest != -1) && (distBest <= dist))
74             continue;
75 
76         distBest = dist,
77         tileDest = tile;
78     }
79 
80     if(tileDest == nullptr)
81     {
82         OD_LOG_ERR("creature=" + creature.getName() + ", myTile=" + Tile::displayAsString(myTile) + ", tileClaim=" + Tile::displayAsString(&tileClaim));
83         creature.popAction();
84         return true;
85     }
86 
87     if(tileDest != myTile)
88     {
89         if(!creature.setDestination(tileDest))
90         {
91             OD_LOG_ERR("creature=" + creature.getName() + ", myTile=" + Tile::displayAsString(myTile) + ", tileClaim=" + Tile::displayAsString(&tileClaim) + ", tileDest=" + Tile::displayAsString(tileDest));
92             creature.popAction();
93         }
94         return true;
95     }
96 
97     // Claim the wall tile
98     const Ogre::Vector3& pos = creature.getPosition();
99     Ogre::Vector3 walkDirection(tileClaim.getX() - pos.x, tileClaim.getY() - pos.y, 0);
100     walkDirection.normalise();
101     creature.setAnimationState(EntityAnimation::claim_anim, true, walkDirection);
102     tileClaim.claimForSeat(creature.getSeat(), creature.getClaimRate());
103     creature.receiveExp(1.5 * creature.getClaimRate() / 20.0);
104 
105     return false;
106 }
107