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

fix: creatures revision #3263

Draft
wants to merge 26 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b91bb0b
implement monster attack spell grouping with random selection
pudimtibia Jan 21, 2025
a239b81
Lua code format - (Stylua)
github-actions[bot] Jan 21, 2025
9ab939b
updated combat logic and created flag for new attack spells configura…
pudimtibia Jan 22, 2025
e190aeb
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 22, 2025
70130fa
Code format - (Clang-format)
github-actions[bot] Jan 22, 2025
7742ebe
Update demon.lua
pudimtibia Jan 22, 2025
c40c935
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 22, 2025
31951f6
Lua code format - (Stylua)
github-actions[bot] Jan 22, 2025
00a5e5c
update: bashmus, girtablilus, some skeletons
pudimtibia Jan 22, 2025
19c290b
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 22, 2025
fd1e0d5
Lua code format - (Stylua)
github-actions[bot] Jan 22, 2025
2c6d141
non-unique loot fixes
pudimtibia Jan 22, 2025
7166f51
non-unique fixes
pudimtibia Jan 22, 2025
769675b
Lua code format - (Stylua)
github-actions[bot] Jan 22, 2025
f49b6f6
update: falcons
pudimtibia Jan 22, 2025
4cd310b
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 22, 2025
f1f3675
Lua code format - (Stylua)
github-actions[bot] Jan 22, 2025
b4466a7
update: some souls
pudimtibia Jan 23, 2025
b30fd7d
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 23, 2025
313d16d
Lua code format - (Stylua)
github-actions[bot] Jan 23, 2025
ba4c455
reset files
pudimtibia Jan 23, 2025
a94d04f
update: flag and functions
pudimtibia Jan 24, 2025
a8a8264
Lua code format - (Stylua)
github-actions[bot] Jan 24, 2025
4f65332
Update register_monster_type.lua
pudimtibia Jan 24, 2025
57add95
Merge branch 'creatures-revision-project' of https://github.com/pudim…
pudimtibia Jan 24, 2025
9c87ea5
Lua code format - (Stylua)
github-actions[bot] Jan 24, 2025
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
3 changes: 3 additions & 0 deletions data/scripts/lib/register_monster_type.lua
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,9 @@ function readSpell(incomingLua, mtype)
if incomingLua.chance then
spell:setChance(incomingLua.chance)
end
if incomingLua.group then
spell:setGroup(incomingLua.group)
end
if incomingLua.range then
spell:setRange(incomingLua.range)
end
Expand Down
121 changes: 62 additions & 59 deletions src/creatures/monsters/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,65 +1115,68 @@ void Monster::onThink_async() {
}

void Monster::doAttacking(uint32_t interval) {
const auto &attackedCreature = getAttackedCreature();
if (!attackedCreature || attackedCreature->isLifeless() || (isSummon() && attackedCreature.get() == this)) {
return;
}

const auto &player = attackedCreature->getPlayer();
if (player && player->isLoginProtected()) {
return;
}

bool updateLook = true;
bool resetTicks = interval != 0;
attackTicks += interval;

const Position &myPos = getPosition();
const Position &targetPos = attackedCreature->getPosition();

for (const spellBlock_t &spellBlock : mType->info.attackSpells) {
bool inRange = false;

if (spellBlock.spell == nullptr || (spellBlock.isMelee && isFleeing())) {
continue;
}

if (canUseSpell(myPos, targetPos, spellBlock, interval, inRange, resetTicks)) {
if (spellBlock.chance >= static_cast<uint32_t>(uniform_random(1, 100))) {
if (updateLook) {
updateLookDirection();
updateLook = false;
}

minCombatValue = spellBlock.minCombatValue;
maxCombatValue = spellBlock.maxCombatValue;

if (spellBlock.spell == nullptr) {
continue;
}

spellBlock.spell->castSpell(getMonster(), attackedCreature);

if (spellBlock.isMelee) {
extraMeleeAttack = false;
}
}
}

if (!inRange && spellBlock.isMelee) {
// melee swing out of reach
extraMeleeAttack = true;
}
}

if (updateLook) {
updateLookDirection();
}

if (resetTicks) {
attackTicks = 0;
}
const auto &attackedCreature = getAttackedCreature();
if (!attackedCreature || (isSummon() && attackedCreature.get() == this)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you remove isLifeless?
#3186

Copy link

@W4gNII W4gNII Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing lifeless in simultaneous attacks can be make a multiple dies of creatures ... its cannot be remmoved or nedded remake this function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you remove isLifeless? #3186

Oops, I'll fix that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it will take some time to be ready, considering that all creatures will be reviewed, I will create a new flag for the creatures

hasGroupedSpells = true,

We check it in the cpp, if it is not there we will continue with the old damage logic. I am making these adjustments and at the same time publishing the changes to the creatures on my live server, this way people can already take advantage of the changes and give the necessary feedback.

return;
}

bool updateLook = true;
bool resetTicks = interval != 0;
attackTicks += interval;

const Position &myPos = getPosition();
const Position &targetPos = attackedCreature->getPosition();

std::map<uint32_t, std::vector<const spellBlock_t*>> groupSpells;
Copy link
Contributor

@mehah mehah Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you do this "grouping" when inserting in mType->info.attackSpells, just order the spells at the end of the insertion. Well, I believe that would be it, I analyzed it superficially.

This suggestion is to mitigate the cost of always creating a map with a vector every time doAttacking is executed.

Copy link
Contributor Author

@pudimtibia pudimtibia Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you do this "grouping" when inserting in mType->info.attackSpells, just order the spells at the end of the insertion. Well, I believe that would be it, I analyzed it superficially.

This suggestion is to mitigate the cost of always creating a map with a vector every time doAttacking is executed.

The isLifeless functionality has been reintroduced, along with a new flag to ensure that spells cast using the old method remain unaffected. My optimization expertise is limited, so any assistance or suggestions for improvement would be greatly appreciated.

Copy link
Contributor

@mehah mehah Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pudimtibia

At first, you just need to check if you have the hasGroupedSpells flag and sort the attackSpells by group.

I think it would be here:

registerMonsterType.attacks = function(mtype, mask)
	if type(mask.attacks) == "table" then
               // maybe
              if mask.hasGroupedSpells then
                  // order by spell group logic
              end

		for _, attack in pairs(mask.attacks) do
			mtype:addAttack(readSpell(attack, mtype))
		end
	end
end

It's better to ask for help from someone who understands this part, I'm not very familiar with Canary.

or even do it directly in c++, it's better to look for the best approach with someone who understands this part that registers monsters through lua.


for (const spellBlock_t &spellBlock : mType->info.attackSpells) {
if (spellBlock.spell == nullptr || (spellBlock.isMelee && isFleeing())) {
continue;
}

uint32_t group = spellBlock.group > 0 ? spellBlock.group : 0;
bool inRange = false;

if (canUseSpell(myPos, targetPos, spellBlock, interval, inRange, resetTicks)) {
if (spellBlock.chance >= static_cast<uint32_t>(uniform_random(1, 100))) {
groupSpells[group].push_back(&spellBlock);
}
}

if (!inRange && spellBlock.isMelee) {
extraMeleeAttack = true; // melee swing out of reach
}
}

for (const auto &[group, spells] : groupSpells) {
if (!spells.empty()) {
const spellBlock_t* selectedSpell = spells[uniform_random(0, spells.size() - 1)];

if (selectedSpell) {
if (updateLook) {
updateLookDirection();
updateLook = false;
}

minCombatValue = selectedSpell->minCombatValue;
maxCombatValue = selectedSpell->maxCombatValue;

selectedSpell->spell->castSpell(getMonster(), attackedCreature);

if (selectedSpell->isMelee) {
extraMeleeAttack = false;
}
}
}
}

if (updateLook) {
updateLookDirection();
}

if (resetTicks) {
attackTicks = 0;
}
}

bool Monster::hasExtraSwing() {
Expand Down
1 change: 1 addition & 0 deletions src/creatures/monsters/monsters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr<MonsterSpell> &spell, spel

sb.speed = spell->interval;
sb.chance = std::min(static_cast<int>(spell->chance), 100);
sb.group = spell->group > 0 ? spell->group : 0;
sb.range = std::min(static_cast<int>(spell->range), MAP_MAX_VIEW_PORT_X * 2);
sb.minCombatValue = std::min(spell->minCombatValue, spell->maxCombatValue);
sb.maxCombatValue = std::max(spell->minCombatValue, spell->maxCombatValue);
Expand Down
3 changes: 3 additions & 0 deletions src/creatures/monsters/monsters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct spellBlock_t {
spellBlock_t(spellBlock_t &&other) noexcept :
spell(std::move(other.spell)),
chance(other.chance),
group(other.group),
speed(other.speed),
range(other.range),
minCombatValue(other.minCombatValue),
Expand All @@ -48,6 +49,7 @@ struct spellBlock_t {

std::shared_ptr<BaseSpell> spell = nullptr;
uint32_t chance = 100;
uint32_t group = 0;
uint32_t speed = 2000;
uint32_t range = 0;
int32_t minCombatValue = 0;
Expand Down Expand Up @@ -230,6 +232,7 @@ class MonsterSpell {
int32_t tickInterval = 0;
int32_t speedChange = 0;
int32_t duration = 0;
int32_t group = 0;

bool isScripted = false;
bool needTarget = false;
Expand Down
13 changes: 13 additions & 0 deletions src/lua/functions/creatures/monster/monster_spell_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ void MonsterSpellFunctions::init(lua_State* L) {
Lua::registerMethod(L, "MonsterSpell", "setType", MonsterSpellFunctions::luaMonsterSpellSetType);
Lua::registerMethod(L, "MonsterSpell", "setScriptName", MonsterSpellFunctions::luaMonsterSpellSetScriptName);
Lua::registerMethod(L, "MonsterSpell", "setChance", MonsterSpellFunctions::luaMonsterSpellSetChance);
Lua::registerMethod(L, "MonsterSpell", "setGroup", MonsterSpellFunctions::luaMonsterSpellSetGroup);
Lua::registerMethod(L, "MonsterSpell", "setInterval", MonsterSpellFunctions::luaMonsterSpellSetInterval);
Lua::registerMethod(L, "MonsterSpell", "setRange", MonsterSpellFunctions::luaMonsterSpellSetRange);
Lua::registerMethod(L, "MonsterSpell", "setCombatValue", MonsterSpellFunctions::luaMonsterSpellSetCombatValue);
Expand Down Expand Up @@ -95,6 +96,18 @@ int MonsterSpellFunctions::luaMonsterSpellSetInterval(lua_State* L) {
return 1;
}

int MonsterSpellFunctions::luaMonsterSpellSetGroup(lua_State* L) {
// monsterSpell:setGroup(group)
const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1);
if (spell) {
spell->group = Lua::getNumber<uint16_t>(L, 2);
Lua::pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}

int MonsterSpellFunctions::luaMonsterSpellSetRange(lua_State* L) {
// monsterSpell:setRange(range)
const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MonsterSpellFunctions {
static int luaMonsterSpellSetType(lua_State* L);
static int luaMonsterSpellSetScriptName(lua_State* L);
static int luaMonsterSpellSetChance(lua_State* L);
static int luaMonsterSpellSetGroup(lua_State* L);
static int luaMonsterSpellSetInterval(lua_State* L);
static int luaMonsterSpellSetRange(lua_State* L);
static int luaMonsterSpellSetCombatValue(lua_State* L);
Expand Down
Loading