Hello!
So.. I've done this feature few months ago for my abandoned 7.6/7.4 project based on TFS 1.3.
I'm going to share it with OTLand community. Feel free to use it in any ways, enjoy!
So.. I've done this feature few months ago for my abandoned 7.6/7.4 project based on TFS 1.3.
I'm going to share it with OTLand community. Feel free to use it in any ways, enjoy!
Preview:
If this gif below is not playing, please Click to Watch Video
On this video Fire Elemental got both flags enabled (set to 1) so he walks above stacked items and destroying (burning) them.
Usage? Description?
Basically this code adds two new monsters flag.
CanPassHeightObjects - default : 0 - if it's set to 1, monster gain ability to walk on stacked items, for example: more than one parcel on yourself - those one where you shouldn't get on in version 7.4/7.6.
CanDestroyItemUnderHim - default : 0 - if it's set to 1, monster gain ability to destroy any item that he walks over it, for example: fire elemental burning everything that he walk through.
CanPassHeightObjects
Luascript.cpp:
Luascript.cpp:
Monster.cpp (This part is stick with destroying items as Fire Elemental, if you don't wan't it or make something different, go ahead! Just read code and don't copy-paste braindeadly )
In function :: bool Monster::getNextStep(Direction& dir, uint32_t& flags) :: search for similar shit below
Monster.h
Monsters.cpp
Monsters.cpp
Monsters.h
Tile.cpp in Tile::queryAdd in after whole "if (hasBitSet(FLAG_PATHFINDING, flags).." make new if with:
C++:
registerMethod("MonsterType", "canPassHeightObjects", LuaScriptInterface::luaMonsterTypeCanPassHeightObjects);
C++:
int32_t LuaScriptInterface::luaMonsterTypeCanPassHeightObjects(lua_State* L)
{
// monsterType:canPassHeightObjects()
MonsterType* monsterType = getUserdata<MonsterType>(L, 1);
if (monsterType) {
pushBoolean(L, monsterType->canPassHeightObjects);
} else {
lua_pushnil(L);
}
return 1;
}
In function :: bool Monster::getNextStep(Direction& dir, uint32_t& flags) :: search for similar shit below
C++:
if (result && (canPassHeightObjects() || canPushItems() || canPushCreatures())) {
const Position& pos = Spells::getCasterPosition(this, dir);
Tile* tile = g_game.map.getTile(pos);
if (tile) {
// fire elemental // Custom
if (canPassHeightObjects() && canDestroyItemUnderHim() ) {
destroyItemUnderHim(tile);
}
if (canPushItems()) {
Monster::pushItems(tile);
}
if (canPushCreatures()) {
Monster::pushCreatures(tile);
}
}
}
return result;
}
C++:
bool canPassHeightObjects() const {
return mType->canPassHeightObjects;
}
C++:
canPassHeightObjects = false;
C++:
} else if (strcasecmp(attrName, "canpassheightobjects") == 0) {
mType->canPassHeightObjects = attr.as_bool();
C++:
bool canPassHeightObjects;
C++:
if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH))) {
if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags) || monster->canPassHeightObjects())) {
return RETURNVALUE_NOTPOSSIBLE;
}
}
Luascript.cpp
Luascript.cpp
Monster.h
Monsters.cpp
Monsters.cpp
Monsters.h
C++:
registerMethod("MonsterType", "canDestroyItemUnderHim", LuaScriptInterface::luaMonsterTypeCanDestroyItemUnderHim);
C++:
int32_t LuaScriptInterface::luaMonsterTypeCanDestroyItemUnderHim(lua_State* L)
{
// monsterType:canDestroyItemUnderHim()
MonsterType* monsterType = getUserdata<MonsterType>(L, 1);
if (monsterType) {
pushBoolean(L, monsterType->canDestroyItemUnderHim);
} else {
lua_pushnil(L);
}
return 1;
}
C++:
bool canDestroyItemUnderHim() const {
return mType->canDestroyItemUnderHim;
}
C++:
canDestroyItemUnderHim = false;
C++:
} else if (strcasecmp(attrName, "candestroyitemunderhim") == 0) {
mType->canDestroyItemUnderHim = mType->canPassHeightObjects = attr.as_bool();
C++:
bool canDestroyItemUnderHim;
Monster.cpp
Monster.h
C++:
void Monster::destroyItemUnderHim(Tile* tile)
{
if (TileItemVector* items = tile->getItemList()) {
uint32_t removeCount = 0;
int32_t downItemSize = tile->getDownItemCount();
for (int32_t i = downItemSize; --i >= 0;) {
Item* item = items->at(i);
if (item && item->hasProperty(CONST_PROP_MOVEABLE) && (item->hasProperty(CONST_PROP_BLOCKPATH)
|| item->hasProperty(CONST_PROP_BLOCKSOLID))) {
g_game.addMagicEffect(tile->getPosition(), CONST_ME_POFF);
if (getName() == "fire elemental") {
g_game.addMagicEffect(tile->getPosition(), CONST_ME_HITBYFIRE);
}
if (Monster::destroyItem(item) && g_game.internalRemoveItem(item) == RETURNVALUE_NOERROR) {
++removeCount;
}
}
}
}
}
C++:
void destroyItemUnderHim(Tile* tile);