Skip to content

Commit

Permalink
Creature/Monster Icons (#4493)
Browse files Browse the repository at this point in the history
* Creature/Monster Icons

Co-Authored-By: KrecikOnDexin <krecikondexin@gmail.com>
Co-Authored-By: Zbizu <Zbizu@users.noreply.github.com>

* remove unused enums

* consistency with constants

* small fix

---------

Co-authored-by: KrecikOnDexin <krecikondexin@gmail.com>
Co-authored-by: Zbizu <Zbizu@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 17, 2024
1 parent 45dc6f9 commit aa7e1fa
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,46 @@ enum ReloadTypes_t : uint8_t
RELOAD_TYPE_WEAPONS,
};

enum MonsterIcon_t : uint8_t
{
MONSTER_ICON_VULNERABLE = 1,
MONSTER_ICON_WEAKENED,
MONSTER_ICON_MELEE,
MONSTER_ICON_INFLUENCED,
MONSTER_ICON_FIENDISH,

MONSTER_ICON_FIRST = MONSTER_ICON_VULNERABLE,
MONSTER_ICON_LAST = MONSTER_ICON_FIENDISH
};

enum CreatureIcon_t : uint8_t
{
CREATURE_ICON_CROSS_WHITE = 1,
CREATURE_ICON_CROSS_WHITE_RED,
CREATURE_ICON_ORB_RED,
CREATURE_ICON_ORB_GREEN,
CREATURE_ICON_ORB_RED_GREEN,
CREATURE_ICON_GEM_GREEN,
CREATURE_ICON_GEM_YELLOW,
CREATURE_ICON_GEM_BLUE,
CREATURE_ICON_GEM_PURPLE,
CREATURE_ICON_GEM_RED,
CREATURE_ICON_PIGEON,
CREATURE_ICON_ENERGY,
CREATURE_ICON_POISON,
CREATURE_ICON_WATER,
CREATURE_ICON_FIRE,
CREATURE_ICON_ICE,
CREATURE_ICON_ARROW_UP,
CREATURE_ICON_ARROW_DOWN,
CREATURE_ICON_WARNING,
CREATURE_ICON_QUESTION,
CREATURE_ICON_CROSS_RED,

CREATURE_ICON_FIRST = CREATURE_ICON_CROSS_WHITE,
CREATURE_ICON_LAST = CREATURE_ICON_CROSS_RED
};

static constexpr int32_t CHANNEL_GUILD = 0x00;
static constexpr int32_t CHANNEL_PARTY = 0x01;
static constexpr int32_t CHANNEL_PRIVATE = 0xFFFF;
Expand Down
10 changes: 10 additions & 0 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,16 @@ void Creature::stopEventWalk()
}
}

void Creature::updateIcons() const
{
SpectatorVec spectators;
g_game.map.getSpectators(spectators, position, true, true);
for (Creature* spectator : spectators) {
assert(dynamic_cast<Player*>(spectator) != nullptr);
static_cast<Player*>(spectator)->sendUpdateCreatureIcons(this);
}
}

void Creature::updateMapCache()
{
Tile* tile;
Expand Down
7 changes: 7 additions & 0 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Player;

using ConditionList = std::list<Condition*>;
using CreatureEventList = std::list<CreatureEvent*>;
using CreatureIconHashMap = std::unordered_map<CreatureIcon_t, uint16_t>;

enum slots_t : uint8_t
{
Expand Down Expand Up @@ -168,6 +169,11 @@ class Creature : virtual public Thing
bool isInvisible() const;
ZoneType_t getZone() const { return getTile()->getZone(); }

// creature icons
CreatureIconHashMap& getIcons() { return creatureIcons; }
const CreatureIconHashMap& getIcons() const { return creatureIcons; }
void updateIcons() const;

// walk functions
void startAutoWalk();
void startAutoWalk(Direction direction);
Expand Down Expand Up @@ -370,6 +376,7 @@ class Creature : virtual public Thing
std::list<Creature*> summons;
CreatureEventList eventsList;
ConditionList conditions;
CreatureIconHashMap creatureIcons;

std::vector<Direction> listWalkDir;

Expand Down
197 changes: 197 additions & 0 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2114,6 +2114,38 @@ void LuaScriptInterface::registerFunctions()
registerEnum(DECAYING_TRUE);
registerEnum(DECAYING_PENDING);

registerEnum(CREATURE_ICON_CROSS_WHITE);
registerEnum(CREATURE_ICON_CROSS_WHITE_RED);
registerEnum(CREATURE_ICON_ORB_RED);
registerEnum(CREATURE_ICON_ORB_GREEN);
registerEnum(CREATURE_ICON_ORB_RED_GREEN);
registerEnum(CREATURE_ICON_GEM_GREEN);
registerEnum(CREATURE_ICON_GEM_YELLOW);
registerEnum(CREATURE_ICON_GEM_BLUE);
registerEnum(CREATURE_ICON_GEM_PURPLE);
registerEnum(CREATURE_ICON_GEM_RED);
registerEnum(CREATURE_ICON_PIGEON);
registerEnum(CREATURE_ICON_ENERGY);
registerEnum(CREATURE_ICON_POISON);
registerEnum(CREATURE_ICON_WATER);
registerEnum(CREATURE_ICON_FIRE);
registerEnum(CREATURE_ICON_ICE);
registerEnum(CREATURE_ICON_ARROW_UP);
registerEnum(CREATURE_ICON_ARROW_DOWN);
registerEnum(CREATURE_ICON_WARNING);
registerEnum(CREATURE_ICON_QUESTION);
registerEnum(CREATURE_ICON_CROSS_RED);
registerEnum(CREATURE_ICON_FIRST);
registerEnum(CREATURE_ICON_LAST);

registerEnum(MONSTER_ICON_VULNERABLE);
registerEnum(MONSTER_ICON_WEAKENED);
registerEnum(MONSTER_ICON_MELEE);
registerEnum(MONSTER_ICON_INFLUENCED);
registerEnum(MONSTER_ICON_FIENDISH);
registerEnum(MONSTER_ICON_FIRST);
registerEnum(MONSTER_ICON_LAST);

// _G
registerGlobalVariable("INDEX_WHEREEVER", INDEX_WHEREEVER);
registerGlobalBoolean("VIRTUAL_PARENT", true);
Expand Down Expand Up @@ -2581,6 +2613,11 @@ void LuaScriptInterface::registerFunctions()

registerMethod("Creature", "getZone", LuaScriptInterface::luaCreatureGetZone);

registerMethod("Creature", "hasIcon", LuaScriptInterface::luaCreatureHasIcon);
registerMethod("Creature", "setIcon", LuaScriptInterface::luaCreatureSetIcon);
registerMethod("Creature", "getIcon", LuaScriptInterface::luaCreatureGetIcon);
registerMethod("Creature", "removeIcon", LuaScriptInterface::luaCreatureRemoveIcon);

registerMethod("Creature", "getStorageValue", LuaScriptInterface::luaCreatureGetStorageValue);
registerMethod("Creature", "setStorageValue", LuaScriptInterface::luaCreatureSetStorageValue);

Expand Down Expand Up @@ -2816,6 +2853,11 @@ void LuaScriptInterface::registerFunctions()
registerMethod("Monster", "isWalkingToSpawn", LuaScriptInterface::luaMonsterIsWalkingToSpawn);
registerMethod("Monster", "walkToSpawn", LuaScriptInterface::luaMonsterWalkToSpawn);

registerMethod("Monster", "hasSpecialIcon", LuaScriptInterface::luaMonsterHasIcon);
registerMethod("Monster", "setSpecialIcon", LuaScriptInterface::luaMonsterSetIcon);
registerMethod("Monster", "getSpecialIcon", LuaScriptInterface::luaMonsterGetIcon);
registerMethod("Monster", "removeSpecialIcon", LuaScriptInterface::luaMonsterRemoveIcon);

// Npc
registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate);
registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare);
Expand Down Expand Up @@ -8704,6 +8746,84 @@ int LuaScriptInterface::luaCreatureGetZone(lua_State* L)
return 1;
}

int LuaScriptInterface::luaCreatureHasIcon(lua_State* L)
{
// creature:hasIcon(iconId)
const Creature* creature = getUserdata<const Creature>(L, 1);
if (creature) {
auto iconId = getNumber<CreatureIcon_t>(L, 2);
pushBoolean(L, creature->getIcons().contains(iconId));
} else {
lua_pushnil(L);
}
return 1;
}

int LuaScriptInterface::luaCreatureSetIcon(lua_State* L)
{
// creature:setIcon(iconId, value)
Creature* creature = getUserdata<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}

auto iconId = getNumber<CreatureIcon_t>(L, 2);
if (iconId > CREATURE_ICON_LAST) {
reportErrorFunc(L, "Invalid Creature Icon Id");
pushBoolean(L, false);
return 1;
}

creature->getIcons()[iconId] = getNumber<uint16_t>(L, 3);
creature->updateIcons();
pushBoolean(L, true);
return 1;
}

int LuaScriptInterface::luaCreatureGetIcon(lua_State* L)
{
// creature:getIcon(iconId)
const Creature* creature = getUserdata<const Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}

auto iconId = getNumber<CreatureIcon_t>(L, 2);
const auto& icons = creature->getIcons();
auto it = icons.find(iconId);
if (it != icons.end()) {
lua_pushinteger(L, it->second);
} else {
lua_pushinteger(L, 0);
}
return 1;
}

int LuaScriptInterface::luaCreatureRemoveIcon(lua_State* L)
{
// creature:removeIcon(iconId)
Creature* creature = getUserdata<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}

auto iconId = getNumber<CreatureIcon_t>(L, 2);
auto& icons = creature->getIcons();
auto it = icons.find(iconId);
if (it != icons.end()) {
icons.erase(it);
creature->updateIcons();
pushBoolean(L, true);
} else {
pushBoolean(L, false);
}

return 1;
}

int LuaScriptInterface::luaCreatureGetStorageValue(lua_State* L)
{
// creature:getStorageValue(key)
Expand Down Expand Up @@ -11478,6 +11598,83 @@ int LuaScriptInterface::luaMonsterWalkToSpawn(lua_State* L)
return 1;
}

int LuaScriptInterface::luaMonsterHasIcon(lua_State* L)
{
// monster:hasSpecialIcon(iconId)
const Monster* monster = getUserdata<const Monster>(L, 1);
if (monster) {
auto iconId = getNumber<MonsterIcon_t>(L, 2);
pushBoolean(L, monster->getSpecialIcons().contains(iconId));
} else {
lua_pushnil(L);
}
return 1;
}

int LuaScriptInterface::luaMonsterSetIcon(lua_State* L)
{
// monster:setSpecialIcon(iconId, value)
Monster* monster = getUserdata<Monster>(L, 1);
if (!monster) {
lua_pushnil(L);
return 1;
}

auto iconId = getNumber<MonsterIcon_t>(L, 2);
if (iconId > MONSTER_ICON_LAST) {
reportErrorFunc(L, "Invalid Monster Icon Id");
pushBoolean(L, false);
return 1;
}

monster->getSpecialIcons()[iconId] = getNumber<uint16_t>(L, 3);
monster->updateIcons();
pushBoolean(L, true);
return 1;
}

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

auto iconId = getNumber<MonsterIcon_t>(L, 2);
const auto& icons = monster->getSpecialIcons();
auto it = icons.find(iconId);
if (it != icons.end()) {
lua_pushinteger(L, it->second);
} else {
lua_pushinteger(L, 0);
}
return 1;
}

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

auto iconId = getNumber<MonsterIcon_t>(L, 2);
auto& icons = monster->getSpecialIcons();
auto it = icons.find(iconId);
if (it != icons.end()) {
icons.erase(it);
monster->updateIcons();
pushBoolean(L, true);
} else {
pushBoolean(L, false);
}
return 1;
}

// Npc
int LuaScriptInterface::luaNpcCreate(lua_State* L)
{
Expand Down
10 changes: 10 additions & 0 deletions src/luascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,11 @@ class LuaScriptInterface

static int luaCreatureGetZone(lua_State* L);

static int luaCreatureHasIcon(lua_State* L);
static int luaCreatureSetIcon(lua_State* L);
static int luaCreatureGetIcon(lua_State* L);
static int luaCreatureRemoveIcon(lua_State* L);

static int luaCreatureGetStorageValue(lua_State* L);
static int luaCreatureSetStorageValue(lua_State* L);

Expand Down Expand Up @@ -1079,6 +1084,11 @@ class LuaScriptInterface
static int luaMonsterIsWalkingToSpawn(lua_State* L);
static int luaMonsterWalkToSpawn(lua_State* L);

static int luaMonsterHasIcon(lua_State* L);
static int luaMonsterSetIcon(lua_State* L);
static int luaMonsterGetIcon(lua_State* L);
static int luaMonsterRemoveIcon(lua_State* L);

// Npc
static int luaNpcCreate(lua_State* L);

Expand Down
6 changes: 6 additions & 0 deletions src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Tile;

using CreatureHashSet = std::unordered_set<Creature*>;
using CreatureList = std::list<Creature*>;
using MonsterIconHashMap = std::unordered_map<MonsterIcon_t, uint16_t>;

enum TargetSearchType_t
{
Expand Down Expand Up @@ -128,11 +129,16 @@ class Monster final : public Creature
BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, bool checkDefense = false,
bool checkArmor = false, bool field = false, bool ignoreResistances = false) override;

// monster icons
MonsterIconHashMap& getSpecialIcons() { return monsterIcons; }
const MonsterIconHashMap& getSpecialIcons() const { return monsterIcons; }

static uint32_t monsterAutoID;

private:
CreatureHashSet friendList;
CreatureList targetList;
MonsterIconHashMap monsterIcons;

std::string name;
std::string nameDescription;
Expand Down
6 changes: 6 additions & 0 deletions src/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,12 @@ class Player final : public Creature, public Cylinder
client->sendUpdateTile(tile, pos);
}
}
void sendUpdateCreatureIcons(const Creature* creature)
{
if (client) {
client->sendUpdateCreatureIcons(creature);
}
}

void sendChannelMessage(const std::string& author, const std::string& text, SpeakClasses type, uint16_t channel)
{
Expand Down
Loading

0 comments on commit aa7e1fa

Please sign in to comment.