Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creature/Monster Icons #4493

Merged
merged 5 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,44 @@ 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_LAST
};

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_LAST
};

MillhioreBT marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -316,6 +316,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 @@ -366,6 +372,7 @@ class Creature : virtual public Thing
std::list<Creature*> summons;
CreatureEventList eventsList;
ConditionList conditions;
CreatureIconHashMap creatureIcons;

std::vector<Direction> listWalkDir;

Expand Down
192 changes: 192 additions & 0 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,34 @@ 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(MONSTER_ICON_VULNERABLE);
registerEnum(MONSTER_ICON_WEAKENED);
registerEnum(MONSTER_ICON_MELEE);
registerEnum(MONSTER_ICON_INFLUENCED);
registerEnum(MONSTER_ICON_FIENDISH);

// _G
registerGlobalVariable("INDEX_WHEREEVER", INDEX_WHEREEVER);
registerGlobalBoolean("VIRTUAL_PARENT", true);
Expand Down Expand Up @@ -2560,6 +2588,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);

// Player
registerClass("Player", "Creature", LuaScriptInterface::luaPlayerCreate);
registerMetaMethod("Player", "__eq", LuaScriptInterface::luaUserdataCompare);
Expand Down Expand Up @@ -2787,6 +2820,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 @@ -8642,6 +8680,83 @@ 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)
Creature* creature = getUserdata<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;
}

// Player
int LuaScriptInterface::luaPlayerCreate(lua_State* L)
{
Expand Down Expand Up @@ -11344,6 +11459,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 @@ -840,6 +840,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);

// Player
static int luaPlayerCreate(lua_State* L);

Expand Down Expand Up @@ -1066,6 +1071,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 @@ -125,11 +126,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 @@ -583,6 +583,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
Loading