diff options
-rw-r--r-- | src/char/char.cpp | 2 | ||||
-rw-r--r-- | src/map/battle.cpp | 32 | ||||
-rw-r--r-- | src/map/clif.cpp | 31 | ||||
-rw-r--r-- | src/map/map.cpp | 17 | ||||
-rw-r--r-- | src/map/map.hpp | 3 | ||||
-rw-r--r-- | src/map/npc.cpp | 15 | ||||
-rw-r--r-- | src/map/pc.cpp | 57 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 50 | ||||
-rw-r--r-- | src/map/skill.cpp | 12 | ||||
-rw-r--r-- | src/map/storage.cpp | 11 | ||||
-rw-r--r-- | src/mmo/clif.t.hpp | 2 | ||||
-rw-r--r-- | src/mmo/enums.hpp | 2 | ||||
-rw-r--r-- | src/mmo/skill.t.hpp | 7 | ||||
-rw-r--r-- | src/shared/lib.cpp | 32 |
14 files changed, 221 insertions, 52 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp index 7ffdd0f..2194ef2 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -777,8 +777,8 @@ void create_online_files(void) stamp_time(timetemp); // write heading FPRINTF(fp2, "<HTML>\n"_fmt); - FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds FPRINTF(fp2, " <HEAD>\n"_fmt); + FPRINTF(fp2, " <META http-equiv=\"refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n"_fmt, char_conf.server_name); FPRINTF(fp2, " </HEAD>\n"_fmt); diff --git a/src/map/battle.cpp b/src/map/battle.cpp index b745e05..d66308d 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -2060,18 +2060,28 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, // 攻撃対象となりうるので攻撃 | Attack because it can be attacked if (sd && sd->status.weapon == ItemLook::W_BOW) { - IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW]; - if (aidx.ok()) - { - if (battle_config.arrow_decrement) - pc_delitem(sd, aidx, 1, 0); - } - else + IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; + + OMATCH_BEGIN_SOME (sdidw, sd->inventory_data[widx]) { - clif_arrow_fail(sd, 0); - return ATK::ZERO; + if (!bool(sdidw->mode & ItemMode::DONT_USE_AMMO)) + { + IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW]; + if (aidx.ok()) + { + if (battle_config.arrow_decrement) + pc_delitem(sd, aidx, 1, 0); + } + else + { + clif_arrow_fail(sd, 0); + return ATK::ZERO; + } + } } + OMATCH_END (); } + wd = battle_calc_weapon_attack(src, target, SkillID::ZERO, 0, 0); // significantly increase injuries for hasted characters @@ -2081,10 +2091,10 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, } if (wd.damage > 0 - && t_sc_data[StatusChange::SC_PHYS_SHIELD].timer + && (t_sc_data[StatusChange::SC_PHYS_SHIELD].timer || t_sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].timer) && target->bl_type == BL::PC) { - int reduction = t_sc_data[StatusChange::SC_PHYS_SHIELD].val1; + int reduction = std::max(t_sc_data[StatusChange::SC_PHYS_SHIELD].val1, t_sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active if (reduction > wd.damage) reduction = wd.damage; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 9edf2af..4d36f17 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -3865,6 +3865,12 @@ RecvResult clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) if (bool(sd->opt1) && sd->opt1 != (Opt1::_stone6)) return rv; + if (sd->sc_data[StatusChange::SC_CANTMOVE].timer) + { + pc_stop_walking(sd, 1); // this is a little hack since client is a bit bugged and still moves several tiles and then gets reset to the position where status was triggered with this it only moves 1 pixel or so and gets set back + return rv; + } + if (sd->invincible_timer) pc_delinvincibletimer(sd); @@ -4617,11 +4623,18 @@ RecvResult clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) clif_displaymessage(sd->sess, "Can't drop items here."_s); return rv; } - if (bool(itemdb_search(sd->status.inventory[fixed.ioff2.unshift()].nameid)->mode & ItemMode::NO_DROP)) + + OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.ioff2.unshift()]) { - clif_displaymessage(sd->sess, "This item can't be dropped."_s); - return rv; + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_DROP) && gmlvl.get_all_bits() < 60) + { + clif_displaymessage(sd->sess, "This item can't be dropped."_s); + return rv; + } } + OMATCH_END (); + if (sd->npc_id || sd->opt1 != Opt1::ZERO) { @@ -4901,11 +4914,17 @@ RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr<map_session_data> sd) if (fixed.zeny_or_ioff2.index != 0 && !fixed.zeny_or_ioff2.ok()) return RecvResult::Error; if (fixed.zeny_or_ioff2.ok()) - if (bool(itemdb_search(sd->status.inventory[fixed.zeny_or_ioff2.unshift()].nameid)->mode & ItemMode::NO_TRADE)) + OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.zeny_or_ioff2.unshift()]) { - clif_displaymessage(sd->sess, "This item can't be traded."_s); - return rv; + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_TRADE) && gmlvl.get_all_bits() < 60) + { + clif_displaymessage(sd->sess, "This item can't be traded."_s); + return rv; + } } + OMATCH_END (); + trade_tradeadditem(sd, fixed.zeny_or_ioff2, fixed.amount); return rv; diff --git a/src/map/map.cpp b/src/map/map.cpp index ff69a56..f8e8bea 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -1241,6 +1241,20 @@ int map_setipport(MapName name, IP4Address ip, int port) } /*========================================== + * creates a hash of a map name + *------------------------------------------ + */ +int map_create_hash(XString str) { + const int k = 67; + const int m = 3067; + int hash = 0; + for (int i = 0; i < str.size(); i++) { + hash += (str[i] * (int)pow(k, i)) % m; + } + return hash; +} + +/*========================================== * マップ1枚読み込み *------------------------------------------ */ @@ -1265,6 +1279,9 @@ bool map_readmap(map_local *m, size_t num, MapName fn) m->npc_num = 0; m->users = 0; + + m->hash = map_create_hash(fn); + really_memzero_this(&m->flag); if (battle_config.pk_mode) m->flag.set(MapFlag::PVP, 1); diff --git a/src/map/map.hpp b/src/map/map.hpp index 56d07a5..8bb5aa7 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -184,7 +184,7 @@ struct map_session_data : block_list, SessionData None, None, None, None, None, None, None, None, None, None, }}; // explicit is better than implicit earray<IOff0, EQUIP, EQUIP::COUNT> equip_index_maybe; - int weight, max_weight; + int weight, max_weight, max_weight_override; MapName mapname_; Session *sess; // use this, you idiots! short to_x, to_y; @@ -531,6 +531,7 @@ struct map_local : map_abstract Point save; Point resave; int mask; + int hash; Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc; }; diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 7d3e62b..0a7bfc2 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -1003,12 +1003,19 @@ int npc_selllist(dumb_ptr<map_session_data> sd, if (!nameid || sd->status.inventory[item_list[i].ioff2.unshift()].amount < item_list[i].count) return 1; - if (bool(itemdb_search(nameid)->mode & ItemMode::NO_SELL_TO_NPC)) + + OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[item_list[i].ioff2.unshift()]) { - //clif_displaymessage(sd->sess, "This item can't be sold to an NPC."_s); - // M+ already outputs "Unable to sell unsellable item." on return value 3. - return 3; + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_SELL_TO_NPC) && gmlvl.get_all_bits() < 60) + { + //clif_displaymessage(sd->sess, "This item can't be sold to an NPC."_s); + // M+ already outputs "Unable to sell unsellable item." on return value 3. + return 3; + } } + OMATCH_END (); + if (sd->trade_partner) return 2; // cant sell while trading z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i].count; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 12af48f..9ef70fe 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -870,6 +870,7 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->quick_regeneration_hp.amount = 0; sd->quick_regeneration_sp.amount = 0; sd->heal_xp = 0; + sd->max_weight_override = 0; sd->canact_tick = tick; sd->canmove_tick = tick; sd->attackabletime = tick; @@ -1121,7 +1122,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_attackrange, b_matk1, b_matk2, b_mdef, b_mdef2; int b_base_atk; int bl; - int aspd_rate, refinedef = 0; + int aspd_rate, speed_rate, refinedef = 0; int str, dstr, dex; int b_pvpchannel = 0; @@ -1473,6 +1474,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) } aspd_rate = sd->aspd_rate; + speed_rate = sd->speed_rate; //攻撃速度増加 | Increased attack speed @@ -1483,6 +1485,9 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->hit += skill_power(sd, SkillID::AC_OWL) / 10; // 20 for 200 } + if (sd->max_weight_override) + sd->max_weight = sd->max_weight_override; + sd->max_weight += 1000; bl = sd->status.base_level; @@ -1548,12 +1553,15 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) /* Slow down if protected */ - if (sd->sc_data[StatusChange::SC_PHYS_SHIELD].timer) - aspd_rate += sd->sc_data[StatusChange::SC_PHYS_SHIELD].val1; + if (sd->sc_data[StatusChange::SC_PHYS_SHIELD].timer || sd->sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].timer) + aspd_rate += std::max(sd->sc_data[StatusChange::SC_PHYS_SHIELD].val1, sd->sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active + + if (sd->sc_data[StatusChange::SC_SLOWMOVE].timer) + speed_rate += sd->sc_data[StatusChange::SC_SLOWMOVE].val1; } - if (sd->speed_rate != 100) - sd->speed = sd->speed * sd->speed_rate / 100; + if (speed_rate != 100) + sd->speed = sd->speed * speed_rate / 100; sd->speed = std::max(sd->speed, 1_ms); if (sd->speed_cap < interval_t::zero()) sd->speed_cap = interval_t::zero(); @@ -1894,6 +1902,14 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) if (!sd->state.lr_flag_is_arrow_2) sd->base_weapon_delay_adjust += interval_t(val); break; + case SP::MAXWEIGHT: + if (!sd->state.lr_flag_is_arrow_2) + sd->max_weight = val; + break; + case SP::MAXWEIGHT_ADD: + if (!sd->state.lr_flag_is_arrow_2) + sd->max_weight += val; + break; default: if (battle_config.error_log) PRINTF("pc_bonus: unknown type %d %d !\n"_fmt, @@ -2404,8 +2420,12 @@ int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n) } P<const ScriptBuffer> script = borrow(*sdidn->use_script); - clif_useitemack(sd, n, amount - 1, 1); - pc_delitem(sd, n, 1, 1); + + if (!bool(sdidn->mode & ItemMode::KEEP_AFTER_USE)) + { + clif_useitemack(sd, n, amount - 1, 1); + pc_delitem(sd, n, 1, 1); + } // activity if (sd) @@ -3717,6 +3737,9 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type) case SP::MAXWEIGHT: val = sd ? sd->max_weight : 0; break; + case SP::MAXWEIGHT_OVERRIDE: + val = sd ? sd->max_weight_override : 0; + break; case SP::BASEEXP: val = sd ? sd->status.base_exp : 0; break; @@ -3866,19 +3889,19 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type) val = sd ? sd->mute.guild : 0; break; case SP::KILLS: - val = sd->activity.kills; + val = sd ? sd->activity.kills : 0; break; case SP::CASTS: - val = sd->activity.casts; + val = sd ? sd->activity.casts : 0; break; case SP::ITEMS_USED: - val = sd->activity.items_used; + val = sd ? sd->activity.items_used : 0; break; case SP::TILES_WALKED: - val = sd->activity.tiles_walked; + val = sd ? sd->activity.tiles_walked : 0; break; case SP::ATTACKS: - val = sd->activity.attacks; + val = sd ? sd->activity.attacks : 0; break; case SP::AUTOMOD: val = sd ? static_cast<int>(sd->automod) : 0; @@ -4044,6 +4067,11 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) sd->max_weight = val; clif_updatestatus(sd, type); break; + case SP::MAXWEIGHT_OVERRIDE: + nullpo_retz(sd); + sd->max_weight_override = val; + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); + break; case SP::HP: nullpo_retz(sd); // TODO: mob mutation @@ -4131,18 +4159,23 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) break; // atm only setting of casts is needed since magic is handled in serverdata but I let the others here as well for whatever reason case SP::KILLS: + nullpo_retz(sd); sd->activity.kills = val; break; case SP::CASTS: + nullpo_retz(sd); sd->activity.casts = val; break; case SP::ITEMS_USED: + nullpo_retz(sd); sd->activity.items_used = val; break; case SP::TILES_WALKED: + nullpo_retz(sd); sd->activity.tiles_walked = val; break; case SP::ATTACKS: + nullpo_retz(sd); sd->activity.attacks = val; break; case SP::AUTOMOD: diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 1efa006..91beb96 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -3920,6 +3920,7 @@ void builtin_sc_start(ScriptState *st) // all those use ms so this checks for < 1s are not needed on those // and it would break the cooldown symbol since many spells have cooldowns less than 1s case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_MBARRIER: case StatusChange::SC_COOLDOWN: case StatusChange::SC_COOLDOWN_MG: @@ -3929,7 +3930,10 @@ void builtin_sc_start(ScriptState *st) case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: - break; + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_SLOWMOVE: + case StatusChange::SC_CANTMOVE: + break; default: // work around old behaviour of: @@ -4362,9 +4366,14 @@ void builtin_getitemlink(ScriptState *st) struct script_data *data; AString buf; data = &AARG(0); - ZString name = conv_str(st, data); + Option<P<struct item_data>> item_data_ = None; + + get_val(st, data); + if (data->is<ScriptDataStr>()) + item_data_ = itemdb_searchname(conv_str(st, data)); + else + item_data_ = itemdb_exists(wrap<ItemNameId>(conv_num(st, data))); - Option<P<struct item_data>> item_data_ = itemdb_searchname(name); OMATCH_BEGIN (item_data_) { OMATCH_CASE_SOME (item_data) @@ -5524,6 +5533,39 @@ void builtin_getmapmaxy(ScriptState *st) } /*========================================== + * Get the hash of a map + *------------------------------------------ + */ +static +void builtin_getmaphash(ScriptState *st) +{ + MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); + push_int<ScriptDataInt>(st->stack, m->hash); +} + +/*========================================== + * Get the map name from a hash + *------------------------------------------ + */ +static +void builtin_getmapnamefromhash(ScriptState *st) +{ + int hash = conv_num(st, &AARG(0)); + MapName mapname; + for (auto& mit : maps_db) + { + map_local *ml = static_cast<map_local *>(mit.second.get()); + if (ml->hash == hash) + { + mapname = ml->name_; + break; + } + } + push_str<ScriptDataStr>(st->stack, mapname); +} + +/*========================================== * Get the NPC's info *------------------------------------------ */ @@ -5787,6 +5829,8 @@ BuiltinFunction builtin_functions[] = BUILTIN(getmap, "?"_s, 's'), BUILTIN(getmapmaxx, "M"_s, 'i'), BUILTIN(getmapmaxy, "M"_s, 'i'), + BUILTIN(getmaphash, "M"_s, 'i'), + BUILTIN(getmapnamefromhash, "i"_s, 's'), BUILTIN(mapexit, ""_s, '\0'), BUILTIN(freeloop, "i"_s, '\0'), BUILTIN(if_then_else, "iii"_s, 'v'), diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 87bbbda..7454cc3 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -201,9 +201,9 @@ int skill_additional_effect(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, } sc_def_phys_shield_spell = 0; - if (battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].timer) + if (battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].timer || battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD_ITEM].timer) sc_def_phys_shield_spell = - battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].val1; + std::max(battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].val1, battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active // 対象の耐性 | Target resistance luk = battle_get_luk(bl); @@ -753,7 +753,9 @@ void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerDa case StatusChange::SC_ATKPOT: /* attack potion [Valaris] */ case StatusChange::SC_MATKPOT: /* magic attack potion [Valaris] */ case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_HASTE: + case StatusChange::SC_SLOWMOVE: calc_flag = 1; break; @@ -765,6 +767,8 @@ void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerDa case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_CANTMOVE: break; /* option2 */ @@ -1030,7 +1034,9 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, case StatusChange::SC_HASTE: case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_MBARRIER: + case StatusChange::SC_SLOWMOVE: calc_flag = 1; break; case StatusChange::SC_HALT_REGENERATE: @@ -1043,6 +1049,8 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_CANTMOVE: break; case StatusChange::SC_FLYING_BACKPACK: updateflag = SP::WEIGHT; diff --git a/src/map/storage.cpp b/src/map/storage.cpp index 54398f3..dc1fe62 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -186,11 +186,16 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount) if (amount < 1 || amount > sd->status.inventory[index].amount) return 0; - if (bool(itemdb_search(sd->status.inventory[index].nameid)->mode & ItemMode::NO_STORAGE)) + OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[index]) { - clif_displaymessage(sd->sess, "This item can't be stored."_s); - return 0; + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_STORAGE) && gmlvl.get_all_bits() < 60) + { + clif_displaymessage(sd->sess, "This item can't be stored."_s); + return 0; + } } + OMATCH_END (); // log_tostorage(sd, index, 0); if (storage_additem(sd, stor, &sd->status.inventory[index], amount) == 0) diff --git a/src/mmo/clif.t.hpp b/src/mmo/clif.t.hpp index f8350a7..c1f7ed3 100644 --- a/src/mmo/clif.t.hpp +++ b/src/mmo/clif.t.hpp @@ -265,6 +265,8 @@ enum class SP : uint16_t WEIGHT = 24, // sent to client MAXWEIGHT = 25, + MAXWEIGHT_ADD = 26, + MAXWEIGHT_OVERRIDE = 27, // sent to client USTR = 32, diff --git a/src/mmo/enums.hpp b/src/mmo/enums.hpp index c4a1b17..377f7d7 100644 --- a/src/mmo/enums.hpp +++ b/src/mmo/enums.hpp @@ -135,6 +135,8 @@ enum class ItemMode : uint8_t NO_TRADE = 2, NO_SELL_TO_NPC = 4, NO_STORAGE = 8, + KEEP_AFTER_USE = 16, + DONT_USE_AMMO = 32, }; ENUM_BITWISE_OPERATORS(ItemMode) } diff --git a/src/mmo/skill.t.hpp b/src/mmo/skill.t.hpp index 782980c..b0b6b8d 100644 --- a/src/mmo/skill.t.hpp +++ b/src/mmo/skill.t.hpp @@ -60,11 +60,16 @@ enum class StatusChange : uint16_t SC_COOLDOWN_ENCH = 76, // Enchanter cooldown SC_COOLDOWN_KOY = 77, // Koyntety cooldown SC_COOLDOWN_UPMARMU = 78, // Upmarmu cooldown + SC_COOLDOWN_SG = 79, // Stone Golem cooldown SC_POISON = 132, // bad; actually used + SC_SLOWMOVE = 133, // slows down movement + SC_CANTMOVE = 134, // stops all movement SC_ATKPOT = 185, // item script - SC_MATKPOT = 186, // unused, but kept for parallel + SC_MATKPOT = 186, // `Matk' spell from items (val1 : power) + + SC_PHYS_SHIELD_ITEM = 193, // `Protect' spell from items, reduce damage (val1: power) can't be chancelled with detsanc // Added for Fate's spells SC_HIDE = 194, // Hide from `detect' magic (PCs only) diff --git a/src/shared/lib.cpp b/src/shared/lib.cpp index 563bff4..37b2e93 100644 --- a/src/shared/lib.cpp +++ b/src/shared/lib.cpp @@ -35,25 +35,37 @@ namespace tmwa { static - void try_read(const io::DirFd& dirfd, ZString filename) + void try_read(const io::DirFd& dirfd, LString dir_path, ZString filename) { io::ReadFile rf(dirfd, filename); if (!rf.is_open()) + { + FPRINTF(stderr, "Could not open %s/%s\n"_fmt, dir_path, filename); abort(); + } AString line; if (!rf.getline(line)) + { + FPRINTF(stderr, "Could not read from %s/%s\n"_fmt, dir_path, filename); abort(); + } } static - void try_write(const io::DirFd& dirfd, ZString filename) + void try_write(const io::DirFd& dirfd, LString dir_path, ZString filename) { io::WriteFile wf(dirfd, filename); if (!wf.is_open()) + { + FPRINTF(stderr, "Could not open %s/%s\n"_fmt, dir_path, filename); abort(); + } wf.put_line("Hello, World!"_s); if (!wf.close()) + { + FPRINTF(stderr, "Could not write to %s/%s\n"_fmt, dir_path, filename); abort(); + } } void check_paths() @@ -65,13 +77,17 @@ namespace tmwa io::DirFd root(portable_root); - io::DirFd etc(root, PACKAGESYSCONFDIR.xslice_t(portable)); - io::DirFd var(root, PACKAGELOCALSTATEDIR.xslice_t(portable)); - io::DirFd share(root, PACKAGEDATADIR.xslice_t(portable)); + LString etc_path = PACKAGESYSCONFDIR.xslice_t(portable); + LString var_path = PACKAGELOCALSTATEDIR.xslice_t(portable); + LString share_path = PACKAGEDATADIR.xslice_t(portable); - try_read(etc, "shared.conf"_s); - try_read(share, "shared.data"_s); - try_write(var, "shared.test"_s); + io::DirFd etc(root, etc_path); + io::DirFd var(root, var_path); + io::DirFd share(root, share_path); + + try_read(etc, etc_path, "shared.conf"_s); + try_read(share, share_path, "shared.data"_s); + try_write(var, var_path, "shared.test"_s); // io::FD::open(); } |