From 2ff2618f8c9a970d1822d5e376fdb67249f63c16 Mon Sep 17 00:00:00 2001
From: Fedja Beader <fedja@protonmail.ch>
Date: Fri, 24 Jan 2025 10:46:23 +0000
Subject: Access mob_db array only once (same for dropitem)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Note: there were some checks before mob.cpp:3743 that I think applied on empty memory? Plus I moved the std::move right at the end of that loop. I'm not too familiar with move mechanics but it seems to work. YMMV.

Approved-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
---
 src/map/clif.cpp       |   2 +-
 src/map/mob.cpp        | 161 +++++++++++++++++++++++++------------------------
 src/map/npc-parse.cpp  |   7 ++-
 src/map/script-fun.cpp |  28 +++++----
 4 files changed, 103 insertions(+), 95 deletions(-)

(limited to 'src')

diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 4d36f17..1b77be6 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -4020,7 +4020,7 @@ RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data>
             dumb_ptr<mob_data> md = bl->is_mob();
             nullpo_retr(rv, md);
 
-            if (md->name != MobName() && md->name != get_mob_db(md->mob_class).name && md->name.size() >= 4)
+            if (md->name.size() >= 4)
                 fixed_95.char_name = stringish<CharName>(md->name);
             else
                 fixed_95.char_name = stringish<CharName>(get_mob_db(md->mob_class).name);
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 3091a83..fc41d19 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -355,24 +355,25 @@ void mob_init(dumb_ptr<mob_data> md)
 {
     int i;
     const Species mob_class = md->mob_class;
-    const int mutations_nr = get_mob_db(mob_class).mutations_nr;
-    const int mutation_power = get_mob_db(mob_class).mutation_power;
-
-    md->stats[mob_stat::LV] = get_mob_db(mob_class).lv;
-    md->stats[mob_stat::MAX_HP] = get_mob_db(mob_class).max_hp;
-    md->stats[mob_stat::STR] = get_mob_db(mob_class).attrs[ATTR::STR];
-    md->stats[mob_stat::AGI] = get_mob_db(mob_class).attrs[ATTR::AGI];
-    md->stats[mob_stat::VIT] = get_mob_db(mob_class).attrs[ATTR::VIT];
-    md->stats[mob_stat::INT] = get_mob_db(mob_class).attrs[ATTR::INT];
-    md->stats[mob_stat::DEX] = get_mob_db(mob_class).attrs[ATTR::DEX];
-    md->stats[mob_stat::LUK] = get_mob_db(mob_class).attrs[ATTR::LUK];
-    md->stats[mob_stat::ATK1] = get_mob_db(mob_class).atk1;
-    md->stats[mob_stat::ATK2] = get_mob_db(mob_class).atk2;
-    md->stats[mob_stat::ADELAY] = get_mob_db(mob_class).adelay.count();
-    md->stats[mob_stat::DEF] = get_mob_db(mob_class).def;
-    md->stats[mob_stat::MDEF] = get_mob_db(mob_class).mdef;
-    md->stats[mob_stat::CRITICAL_DEF] = get_mob_db(mob_class).critical_def;
-    md->stats[mob_stat::SPEED] = get_mob_db(mob_class).speed.count();
+    const mob_db_& mob_info = get_mob_db(mob_class);
+    const int mutations_nr = mob_info.mutations_nr;
+    const int mutation_power = mob_info.mutation_power;
+
+    md->stats[mob_stat::LV] = mob_info.lv;
+    md->stats[mob_stat::MAX_HP] = mob_info.max_hp;
+    md->stats[mob_stat::STR] = mob_info.attrs[ATTR::STR];
+    md->stats[mob_stat::AGI] = mob_info.attrs[ATTR::AGI];
+    md->stats[mob_stat::VIT] = mob_info.attrs[ATTR::VIT];
+    md->stats[mob_stat::INT] = mob_info.attrs[ATTR::INT];
+    md->stats[mob_stat::DEX] = mob_info.attrs[ATTR::DEX];
+    md->stats[mob_stat::LUK] = mob_info.attrs[ATTR::LUK];
+    md->stats[mob_stat::ATK1] = mob_info.atk1;
+    md->stats[mob_stat::ATK2] = mob_info.atk2;
+    md->stats[mob_stat::ADELAY] = mob_info.adelay.count();
+    md->stats[mob_stat::DEF] = mob_info.def;
+    md->stats[mob_stat::MDEF] = mob_info.mdef;
+    md->stats[mob_stat::CRITICAL_DEF] = mob_info.critical_def;
+    md->stats[mob_stat::SPEED] = mob_info.speed.count();
     md->stats[mob_stat::XP_BONUS] = MOB_XP_BONUS_BASE;
 
     for (i = 0; i < mutations_nr; i++)
@@ -2596,6 +2597,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
     );
 
     {
+        const mob_db_& mob_info = get_mob_db(md->mob_class);
         struct DmgLogParty
         {
             PartyPair p;
@@ -2660,23 +2662,23 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
                 per = 1;
 
             base_exp =
-                ((get_mob_db(md->mob_class).base_exp *
+                ((mob_info.base_exp *
                   md->stats[mob_stat::XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256;
             if (base_exp < 1)
                 base_exp = 1;
             if (sd && battle_config.pk_mode == 1
-                && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+                && (mob_info.lv - sd->status.base_level >= 20))
             {
                 base_exp *= 1.15;   // pk_mode additional exp if monster >20 levels [Valaris]
             }
             if (md->state.special_mob_ai >= 1
                 && battle_config.alchemist_summon_reward != 1)
                 base_exp = 0;   // Added [Valaris]
-            job_exp = get_mob_db(md->mob_class).job_exp * per / 256;
+            job_exp = mob_info.job_exp * per / 256;
             if (job_exp < 1)
                 job_exp = 1;
             if (sd && battle_config.pk_mode == 1
-                && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+                && (mob_info.lv - sd->status.base_level >= 20))
             {
                 job_exp *= 1.15;    // pk_mode additional exp if monster >20 levels [Valaris]
             }
@@ -2730,13 +2732,14 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
                 if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)    // Added [Valaris]
                     break;      // End
 
-                if (!get_mob_db(md->mob_class).dropitem[i].nameid)
+                const auto& drop_info = mob_info.dropitem[i];
+                if (!drop_info.nameid)
                     continue;
-                random_::Fixed<int, 10000> drop_rate = get_mob_db(md->mob_class).dropitem[i].p;
+                random_::Fixed<int, 10000> drop_rate = drop_info.p;
                 if (sd && battle_config.drops_by_luk > 0)
                     drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100;   // drops affected by luk [Valaris]
                 if (sd && battle_config.pk_mode == 1
-                    && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+                    && (mob_info.lv - sd->status.base_level >= 20))
                     drop_rate.num *= 1.25;  // pk_mode increase drops if 20 level difference [Valaris]
 
                 // server-wide drop rate scaling
@@ -2745,7 +2748,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
                     continue;
 
                 struct delay_item_drop ditem {};
-                ditem.nameid = get_mob_db(md->mob_class).dropitem[i].nameid;
+                ditem.nameid = drop_info.nameid;
                 ditem.amount = 1;
                 ditem.m = md->bl_m;
                 ditem.x = md->bl_x;
@@ -3503,40 +3506,39 @@ int mobskill_event(dumb_ptr<mob_data> md, BF flag)
 static
 int mob_makedummymobdb(Species mob_class)
 {
-    int i;
-
-    SNPRINTF(get_mob_db(mob_class).name, 24, "mob%d"_fmt, mob_class);
-    SNPRINTF(get_mob_db(mob_class).jname, 24, "mob%d"_fmt, mob_class);
-    get_mob_db(mob_class).lv = 1;
-    get_mob_db(mob_class).max_hp = 1000;
-    get_mob_db(mob_class).max_sp = 1;
-    get_mob_db(mob_class).base_exp = 2;
-    get_mob_db(mob_class).job_exp = 1;
-    get_mob_db(mob_class).range = 1;
-    get_mob_db(mob_class).atk1 = 7;
-    get_mob_db(mob_class).atk2 = 10;
-    get_mob_db(mob_class).def = 0;
-    get_mob_db(mob_class).mdef = 0;
-    get_mob_db(mob_class).attrs[ATTR::STR] = 1;
-    get_mob_db(mob_class).attrs[ATTR::AGI] = 1;
-    get_mob_db(mob_class).attrs[ATTR::VIT] = 1;
-    get_mob_db(mob_class).attrs[ATTR::INT] = 1;
-    get_mob_db(mob_class).attrs[ATTR::DEX] = 6;
-    get_mob_db(mob_class).attrs[ATTR::LUK] = 2;
-    get_mob_db(mob_class).range2 = 10;
-    get_mob_db(mob_class).range3 = 10;
-    get_mob_db(mob_class).size = 0; // 1
-    get_mob_db(mob_class).race = Race::formless;
-    get_mob_db(mob_class).element = LevelElement{0, Element::neutral};
-    get_mob_db(mob_class).mode = MobMode::ZERO;
-    get_mob_db(mob_class).speed = 300_ms;
-    get_mob_db(mob_class).adelay = 1000_ms;
-    get_mob_db(mob_class).amotion = 500_ms;
-    get_mob_db(mob_class).dmotion = 500_ms;
-    for (i = 0; i < MaxDrops; i++)
-    {
-        get_mob_db(mob_class).dropitem[i].nameid = ItemNameId();
-        get_mob_db(mob_class).dropitem[i].p.num = 0;
+    mob_db_& mob_info = get_mob_db(mob_class);
+    SNPRINTF(mob_info.name, 24, "mob%d"_fmt, mob_class);
+    SNPRINTF(mob_info.jname, 24, "mob%d"_fmt, mob_class);
+    mob_info.lv = 1;
+    mob_info.max_hp = 1000;
+    mob_info.max_sp = 1;
+    mob_info.base_exp = 2;
+    mob_info.job_exp = 1;
+    mob_info.range = 1;
+    mob_info.atk1 = 7;
+    mob_info.atk2 = 10;
+    mob_info.def = 0;
+    mob_info.mdef = 0;
+    mob_info.attrs[ATTR::STR] = 1;
+    mob_info.attrs[ATTR::AGI] = 1;
+    mob_info.attrs[ATTR::VIT] = 1;
+    mob_info.attrs[ATTR::INT] = 1;
+    mob_info.attrs[ATTR::DEX] = 6;
+    mob_info.attrs[ATTR::LUK] = 2;
+    mob_info.range2 = 10;
+    mob_info.range3 = 10;
+    mob_info.size = 0; // 1
+    mob_info.race = Race::formless;
+    mob_info.element = LevelElement{0, Element::neutral};
+    mob_info.mode = MobMode::ZERO;
+    mob_info.speed = 300_ms;
+    mob_info.adelay = 1000_ms;
+    mob_info.amotion = 500_ms;
+    mob_info.dmotion = 500_ms;
+    for (int i = 0; i < MaxDrops; i++)
+    {
+        mob_info.dropitem[i].nameid = ItemNameId();
+        mob_info.dropitem[i].p.num = 0;
     }
     return 0;
 }
@@ -3656,56 +3658,55 @@ bool mob_readdb(ZString filename)
                 continue;
             }
 
-            if (get_mob_db(mob_class).base_exp < 0)
+            if (mdbv.base_exp < 0)
             {
                 PRINTF("bad mob line: Xp needs to be greater than 0.  %s\n"_fmt, line);
                 rv = false;
                 continue;
             }
-            if (get_mob_db(mob_class).base_exp > 1000000000)
+            if (mdbv.base_exp > 1000000000)
             {
                 PRINTF("bad mob line: Xp needs to be less than 1000000000.  %s\n"_fmt, line);
                 rv = false;
                 continue;
             }
-            if (get_mob_db(mob_class).job_exp < 0)
+            if (mdbv.job_exp < 0)
             {
                 PRINTF("bad mob line: Job Xp needs to be greater than 0.  %s\n"_fmt, line);
                 rv = false;
                 continue;
             }
-            if (get_mob_db(mob_class).job_exp > 1000000000)
+            if (mdbv.job_exp > 1000000000)
             {
                 PRINTF("bad mob line: Job Xp needs to be less than 1000000000.  %s\n"_fmt, line);
                 rv = false;
                 continue;
             }
 
-            // TODO move this lower
-            get_mob_db(mob_class) = std::move(mdbv);
-
             for (int i = 0; i < MaxDrops; i++)
             {
-                int rate = get_mob_db(mob_class).dropitem[i].p.num;
+                int rate = mdbv.dropitem[i].p.num;
                 if (rate < 1) rate = 1;
                 if (rate > 10000) rate = 10000;
-                get_mob_db(mob_class).dropitem[i].p.num = rate;
+                mdbv.dropitem[i].p.num = rate;
             }
 
 
-            get_mob_db(mob_class).skills.clear();
+            mdbv.skills.clear();
+
+            mdbv.hair = 0;
+            mdbv.hair_color = 0;
+            mdbv.weapon = 0;
+            mdbv.shield = ItemNameId();
+            mdbv.head_top = ItemNameId();
+            mdbv.head_mid = ItemNameId();
+            mdbv.head_buttom = ItemNameId();
+            mdbv.clothes_color = 0;    //Add for player monster dye - Valaris
 
-            get_mob_db(mob_class).hair = 0;
-            get_mob_db(mob_class).hair_color = 0;
-            get_mob_db(mob_class).weapon = 0;
-            get_mob_db(mob_class).shield = ItemNameId();
-            get_mob_db(mob_class).head_top = ItemNameId();
-            get_mob_db(mob_class).head_mid = ItemNameId();
-            get_mob_db(mob_class).head_buttom = ItemNameId();
-            get_mob_db(mob_class).clothes_color = 0;    //Add for player monster dye - Valaris
+            if (mdbv.base_exp == 0)
+                mdbv.base_exp = mob_gen_exp(&mdbv);
 
-            if (get_mob_db(mob_class).base_exp == 0)
-                get_mob_db(mob_class).base_exp = mob_gen_exp(&get_mob_db(mob_class));
+            get_mob_db(mob_class) = std::move(mdbv);
         }
         PRINTF("read %s done\n"_fmt, filename);
     }
diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp
index df1a09a..c6564fb 100644
--- a/src/map/npc-parse.cpp
+++ b/src/map/npc-parse.cpp
@@ -273,15 +273,16 @@ bool npc_load_monster(ast::npc::Monster& monster)
         md->bl_m = m;
         md->bl_x = x;
         md->bl_y = y;
-        MobName expected = get_mob_db(mob_class).jname;
+        const mob_db_& mob_info = get_mob_db(md->mob_class);
+        MobName expected = mob_info.jname;
         if (monster.name.data != expected)
         {
             monster.name.span.warning(STRPRINTF("Visible label/jname should match: %s"_fmt, expected));
         }
         if (monster.name.data == ENGLISH_NAME)
-            md->name = get_mob_db(mob_class).name;
+            md->name = mob_info.name;
         else if (monster.name.data == JAPANESE_NAME)
-            md->name = get_mob_db(mob_class).jname;
+            md->name = mob_info.jname;
         else
             md->name = monster.name.data;
 
diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp
index 91beb96..feaf388 100644
--- a/src/map/script-fun.cpp
+++ b/src/map/script-fun.cpp
@@ -3022,7 +3022,9 @@ void builtin_mobinfo_droparrays(ScriptState *st)
     }
     
     for (int i = 0; i < MaxDrops; ++i)
-        if (get_mob_db(mob_id).dropitem[i].nameid)
+    {
+        auto& dropitem = get_mob_db(mob_id).dropitem[i];
+        if (dropitem.nameid)
         {
             status = 1;
             switch (request)
@@ -3030,15 +3032,15 @@ void builtin_mobinfo_droparrays(ScriptState *st)
                 case MobInfo_DropArrays::IDS:
                     if (name.startswith(".@"_s))
                         {
-                            struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid)});
+                            struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(dropitem.nameid)});
                             set_scope_reg(st, reg.iplus(i), &vd);
                         }
                     else
-                        set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid));
+                        set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(dropitem.nameid));
                     break;
                 case MobInfo_DropArrays::NAMES:
                     {
-                        Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid));
+                        Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid));
                         RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
 
                         if (name.startswith(".@"_s))
@@ -3053,11 +3055,11 @@ void builtin_mobinfo_droparrays(ScriptState *st)
                 case MobInfo_DropArrays::PERCENTS:
                     if (name.startswith(".@"_s))
                         {
-                            struct script_data vd = script_data(ScriptDataInt{get_mob_db(mob_id).dropitem[i].p.num});
+                            struct script_data vd = script_data(ScriptDataInt{dropitem.p.num});
                             set_scope_reg(st, reg.iplus(i), &vd);
                         }
                     else
-                        set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), get_mob_db(mob_id).dropitem[i].p.num);
+                        set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), dropitem.p.num);
                     break;
             }
         }
@@ -3067,7 +3069,7 @@ void builtin_mobinfo_droparrays(ScriptState *st)
                 status = 2;
             break;
         }
-
+    }
     push_int<ScriptDataInt>(st->stack, status);
 }
 
@@ -3097,16 +3099,19 @@ void builtin_getmobdrops(ScriptState *st)
 
     status = 1;
 
+    const mob_db_& mob_info = get_mob_db(mob_id);
     for (; i < MaxDrops; ++i)
-        if (get_mob_db(mob_id).dropitem[i].nameid)
+    {
+        auto& dropitem = mob_info.dropitem[i];
+        if (dropitem.nameid)
         {
-            set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), get_mob_db(mob_id).dropitem[i].p.num);
+            set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), dropitem.p.num);
 
-            Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid));
+            Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid));
             RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
             set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_name$"_s), i), item_name);
 
-            set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), get_mob_db(mob_id).dropitem[i].p.num);
+            set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), dropitem.p.num);
         }
         else
         {
@@ -3114,6 +3119,7 @@ void builtin_getmobdrops(ScriptState *st)
                 status = 2;
             break;
         }
+    }
 
     if (status == 1)
         set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_count"_s), 0), i);
-- 
cgit v1.2.3-70-g09d2