From 98e5e62ef7a04977146fdbfbc3166dad5d082da0 Mon Sep 17 00:00:00 2001 From: mekolat Date: Thu, 18 Jun 2015 23:41:58 -0400 Subject: add scope, npc/mob variables; add new get/set --- src/map/map.hpp | 14 +- src/map/pc.cpp | 8 +- src/map/pc.hpp | 8 +- src/map/script-call-internal.hpp | 18 ++- src/map/script-call.cpp | 87 ++++++++++--- src/map/script-fun.cpp | 272 +++++++++++++++++++++++++++++++++------ src/map/script-parse.cpp | 5 + 7 files changed, 339 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/map/map.hpp b/src/map/map.hpp index a2d0f5d..72d5dd3 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -77,6 +77,13 @@ struct block_list short bl_x, bl_y; BL bl_type; + // register keys are ints (interned) + // Not anymore! Well, sort of. + DMap regm; + // can't be DMap because we want predictable .c_str()s + // TODO this can change now + Map regstrm; + // This deletes the copy-ctor also // TODO give proper ctors. block_list& operator = (block_list&&) = delete; @@ -251,13 +258,6 @@ struct map_session_data : block_list, SessionData int die_counter; - // register keys are ints (interned) - // Not anymore! Well, sort of. - DMap regm; - // can't be DMap because we want predictable .c_str()s - // TODO this can change now - Map regstrm; - earray sc_data; AccountId trade_partner; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 7f7512c..f65e2b4 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -3814,7 +3814,7 @@ int pc_changelook(dumb_ptr sd, LOOK type, int val) * script用変数の値を読む *------------------------------------------ */ -int pc_readreg(dumb_ptr sd, SIR reg) +int pc_readreg(dumb_ptr sd, SIR reg) { nullpo_retz(sd); @@ -3825,7 +3825,7 @@ int pc_readreg(dumb_ptr sd, SIR reg) * script用変数の値を設定 *------------------------------------------ */ -void pc_setreg(dumb_ptr sd, SIR reg, int val) +void pc_setreg(dumb_ptr sd, SIR reg, int val) { nullpo_retv(sd); @@ -3836,7 +3836,7 @@ void pc_setreg(dumb_ptr sd, SIR reg, int val) * script用文字列変数の値を読む *------------------------------------------ */ -ZString pc_readregstr(dumb_ptr sd, SIR reg) +ZString pc_readregstr(dumb_ptr sd, SIR reg) { nullpo_retr(ZString(), sd); @@ -3848,7 +3848,7 @@ ZString pc_readregstr(dumb_ptr sd, SIR reg) * script用文字列変数の値を設定 *------------------------------------------ */ -void pc_setregstr(dumb_ptr sd, SIR reg, RString str) +void pc_setregstr(dumb_ptr sd, SIR reg, RString str) { nullpo_retv(sd); diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 3a35330..6bcfadb 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -144,10 +144,10 @@ int pc_changelook(dumb_ptr, LOOK, int); int pc_readparam(dumb_ptr, SP); int pc_setparam(dumb_ptr, SP, int); -int pc_readreg(dumb_ptr, SIR); -void pc_setreg(dumb_ptr, SIR, int); -ZString pc_readregstr(dumb_ptr sd, SIR reg); -void pc_setregstr(dumb_ptr sd, SIR reg, RString str); +int pc_readreg(dumb_ptr, SIR); +void pc_setreg(dumb_ptr, SIR, int); +ZString pc_readregstr(dumb_ptr sd, SIR reg); +void pc_setregstr(dumb_ptr sd, SIR reg, RString str); void update_quest(dumb_ptr sd, VarName quest_var, int value); void update_allquest(dumb_ptr sd); int pc_readglobalreg(dumb_ptr, VarName ); diff --git a/src/map/script-call-internal.hpp b/src/map/script-call-internal.hpp index a887eb8..b3dfb5a 100644 --- a/src/map/script-call-internal.hpp +++ b/src/map/script-call-internal.hpp @@ -25,6 +25,8 @@ #include "../mmo/ids.hpp" +#include "../strings/rstring.hpp" +#include "../generic/db.hpp" #include "script-persist.hpp" @@ -55,6 +57,13 @@ public: ScriptPointer scriptp, new_scriptp; int defsp, new_defsp, freeloop; int is_true = 0; + + // register keys are ints (interned) + // Not anymore! Well, sort of. + DMap regm; + // can't be DMap because we want predictable .c_str()s + // TODO this can change now + Map regstrm; }; void run_func(ScriptState *st); @@ -70,13 +79,14 @@ enum class ScriptEndState }; dumb_ptr script_rid2sd(ScriptState *st); -void get_val(dumb_ptr sd, struct script_data *data); +void get_val(dumb_ptr sd, struct script_data *data); __attribute__((deprecated)) void get_val(ScriptState *st, struct script_data *data); struct script_data get_val2(ScriptState *st, SIR reg); -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct script_data vd); -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, int id); -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, RString zd); +void set_scope_reg(ScriptState *, SIR, struct script_data); +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct script_data vd); +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, int id); +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, RString zd); __attribute__((warn_unused_result)) RString conv_str(ScriptState *st, struct script_data *data); __attribute__((warn_unused_result)) diff --git a/src/map/script-call.cpp b/src/map/script-call.cpp index b8f531a..2ebfca3 100644 --- a/src/map/script-call.cpp +++ b/src/map/script-call.cpp @@ -78,7 +78,7 @@ dumb_ptr script_rid2sd(ScriptState *st) * 変数の読み取り *------------------------------------------ */ -void get_val(dumb_ptr sd, struct script_data *data) +void get_val(dumb_ptr sd, struct script_data *data) { MATCH_BEGIN (*data) { @@ -88,7 +88,7 @@ void get_val(dumb_ptr sd, struct script_data *data) PRINTF("get_val error param SP::%d\n"_fmt, u.reg.sp()); int numi = 0; if (sd) - numi = pc_readparam(sd, u.reg.sp()); + numi = pc_readparam(sd->is_player(), u.reg.sp()); *data = ScriptDataInt{numi}; } MATCH_CASE (const ScriptDataVariable&, u) @@ -106,7 +106,7 @@ void get_val(dumb_ptr sd, struct script_data *data) if (postfix == '$') { RString str; - if (prefix == '@') + if (prefix == '@' || prefix == '.') { if (sd) str = pc_readregstr(sd, u.reg); @@ -130,7 +130,7 @@ void get_val(dumb_ptr sd, struct script_data *data) else { int numi = 0; - if (prefix == '@') + if (prefix == '@' || prefix == '.') { if (sd) numi = pc_readreg(sd, u.reg); @@ -144,18 +144,18 @@ void get_val(dumb_ptr sd, struct script_data *data) if (name[1] == '#') { if (sd) - numi = pc_readaccountreg2(sd, name); + numi = pc_readaccountreg2(sd->is_player(), name); } else { if (sd) - numi = pc_readaccountreg(sd, name); + numi = pc_readaccountreg(sd->is_player(), name); } } else { if (sd) - numi = pc_readglobalreg(sd, name); + numi = pc_readglobalreg(sd->is_player(), name); } *data = ScriptDataInt{numi}; } @@ -166,8 +166,38 @@ void get_val(dumb_ptr sd, struct script_data *data) void get_val(ScriptState *st, struct script_data *data) { - dumb_ptr sd = st->rid ? map_id2sd(st->rid) : nullptr; - get_val(sd, data); + dumb_ptr bl = nullptr; + MATCH_BEGIN (*data) + { + MATCH_CASE (const ScriptDataParam&, u) + { + bl = map_id2bl(st->rid); + } + MATCH_CASE (const ScriptDataVariable&, u) + { + ZString name_ = variable_names.outtern(u.reg.base()); + VarName name = stringish(name_); + char prefix = name.front(); + if (prefix == '.' && name[1] == '@') + { + if (name.back() == '$') + { + Option> s = st->regstrm.search(u.reg); + ZString val = s.map([](P s_) -> ZString { return *s_; }).copy_or(""_s); + *data = ScriptDataStr{val}; + } + else + *data = ScriptDataInt{st->regm.get(u.reg)}; + return; + } + if (prefix == '.' && st->oid) + bl = map_id2bl(st->oid); + else if (prefix != '$' && st->rid) + bl = map_id2bl(st->rid); + } + } + MATCH_END (); + get_val(bl, data); } /*========================================== @@ -185,12 +215,12 @@ struct script_data get_val2(ScriptState *st, SIR reg) * 変数設定用 *------------------------------------------ */ -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct script_data vd) +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct script_data vd) { if (type == VariableCode::PARAM) { int val = vd.get_if()->numi; - pc_setparam(sd, reg.sp(), val); + pc_setparam(sd->is_player(), reg.sp(), val); return; } assert (type == VariableCode::VARIABLE); @@ -203,7 +233,7 @@ void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct s if (postfix == '$') { RString str = vd.get_if()->str; - if (prefix == '@') + if (prefix == '@' || prefix == '.') { pc_setregstr(sd, reg, str); } @@ -219,7 +249,7 @@ void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct s else { int val = vd.get_if()->numi; - if (prefix == '@') + if (prefix == '@' || prefix == '.') { pc_setreg(sd, reg, val); } @@ -230,24 +260,45 @@ void set_reg(dumb_ptr sd, VariableCode type, SIR reg, struct s else if (prefix == '#') { if (name[1] == '#') - pc_setaccountreg2(sd, name, val); + pc_setaccountreg2(sd->is_player(), name, val); else - pc_setaccountreg(sd, name, val); + pc_setaccountreg(sd->is_player(), name, val); } else { - pc_setglobalreg(sd, name, val); + pc_setglobalreg(sd->is_player(), name, val); + } + } +} + +void set_scope_reg(ScriptState *st, SIR reg, struct script_data vd) +{ + ZString name = variable_names.outtern(reg.base()); + if (name.back() == '$') + { + if (auto *u = vd.get_if()) + { + if (!u->str) + { + st->regstrm.erase(reg); + return; + } + st->regstrm.insert(reg, u->str); } + else + st->regstrm.erase(reg); } + else if (auto *u = vd.get_if()) + st->regm.put(reg, u->numi); } -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, int id) +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, int id) { struct script_data vd = ScriptDataInt{id}; set_reg(sd, type, reg, vd); } -void set_reg(dumb_ptr sd, VariableCode type, SIR reg, RString zd) +void set_reg(dumb_ptr sd, VariableCode type, SIR reg, RString zd) { struct script_data vd = ScriptDataStr{zd}; set_reg(sd, type, reg, vd); diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 4ef6499..f215d73 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -780,7 +780,7 @@ void builtin_foreach(ScriptState *st) *---------------------------------------- */ static -void builtin_destroypuppet(ScriptState *st) +void builtin_destroy(ScriptState *st) { BlockId id; if (HARG(0)) @@ -909,37 +909,116 @@ void builtin_puppet(ScriptState *st) static void builtin_set(ScriptState *st) { - dumb_ptr sd = nullptr; + BlockId id; + dumb_ptr bl = nullptr; if (auto *u = AARG(0).get_if()) { SIR reg = u->reg; - sd = script_rid2sd(st); + if(HARG(2)) + { + struct script_data *sdata = &AARG(2); + get_val(st, sdata); + CharName name; + if (sdata->is()) + { + name = stringish(ZString(conv_str(st, sdata))); + if (name.to__actual()) + bl = map_nick2sd(name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + } + + else + bl = script_rid2sd(st)->is_player(); + if (bl == nullptr) + return; int val = conv_num(st, &AARG(1)); - set_reg(sd, VariableCode::PARAM, reg, val); + set_reg(bl, VariableCode::PARAM, reg, val); return; } SIR reg = AARG(0).get_if()->reg; ZString name = variable_names.outtern(reg.base()); - char prefix = name.front(); - char postfix = name.back(); + VarName name_ = stringish(name); + char prefix = name_.front(); + char postfix = name_.back(); if (prefix != '$') - sd = script_rid2sd(st); + { + if(HARG(2)) + { + struct script_data *sdata = &AARG(2); + get_val(st, sdata); + if(prefix == '.') + { + if (name_[1] == '@') + { + PRINTF("builtin_set: illegal scope!\n"_fmt); + return; + } + NpcName n_name; + if (sdata->is()) + { + n_name = stringish(ZString(conv_str(st, sdata))); + bl = npc_name2id(n_name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + } + else + { + CharName c_name; + if (sdata->is()) + { + c_name = stringish(ZString(conv_str(st, sdata))); + if (c_name.to__actual()) + bl = map_nick2sd(c_name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + } + } + else + { + if(prefix == '.') + { + if (name_[1] == '@') + { + set_scope_reg(st, reg, AARG(1)); + return; + } + bl = map_id2bl(st->oid)->is_npc(); + } + else + bl = map_id2bl(st->rid)->is_player(); + } + if (bl == nullptr) + return; + } if (postfix == '$') { // 文字列 RString str = conv_str(st, &AARG(1)); - set_reg(sd, VariableCode::VARIABLE, reg, str); + set_reg(bl, VariableCode::VARIABLE, reg, str); } else { // 数値 int val = conv_num(st, &AARG(1)); - set_reg(sd, VariableCode::VARIABLE, reg, val); + set_reg(bl, VariableCode::VARIABLE, reg, val); } } @@ -951,26 +1030,30 @@ void builtin_set(ScriptState *st) static void builtin_setarray(ScriptState *st) { - dumb_ptr sd = nullptr; + dumb_ptr bl = nullptr; SIR reg = AARG(0).get_if()->reg; ZString name = variable_names.outtern(reg.base()); char prefix = name.front(); char postfix = name.back(); - if (prefix != '$' && prefix != '@') + if (prefix != '$' && prefix != '@' && prefix != '.') { PRINTF("builtin_setarray: illegal scope!\n"_fmt); return; } - if (prefix != '$') - sd = script_rid2sd(st); + if (prefix == '.' && name[1] != '@') + bl = map_id2bl(st->oid)->is_npc(); + else if (prefix != '$') + bl = map_id2bl(st->rid)->is_player(); for (int j = 0, i = 1; i < st->end - st->start - 2 && j < 256; i++, j++) { - if (postfix == '$') - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), conv_str(st, &AARG(i))); + if (prefix == '.' && name[1] == '@') + set_scope_reg(st, reg.iplus(j), AARG(i)); + else if (postfix == '$') + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), conv_str(st, &AARG(i))); else - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), conv_num(st, &AARG(i))); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), conv_num(st, &AARG(i))); } } @@ -981,27 +1064,31 @@ void builtin_setarray(ScriptState *st) static void builtin_cleararray(ScriptState *st) { - dumb_ptr sd = nullptr; + dumb_ptr bl = nullptr; SIR reg = AARG(0).get_if()->reg; ZString name = variable_names.outtern(reg.base()); char prefix = name.front(); char postfix = name.back(); int sz = conv_num(st, &AARG(2)); - if (prefix != '$' && prefix != '@') + if (prefix != '$' && prefix != '@' && prefix != '.') { PRINTF("builtin_cleararray: illegal scope!\n"_fmt); return; } - if (prefix != '$') - sd = script_rid2sd(st); + if (prefix == '.' && name[1] != '@') + bl = map_id2bl(st->oid)->is_npc(); + else if (prefix != '$') + bl = map_id2bl(st->rid)->is_player(); for (int i = 0; i < sz; i++) { - if (postfix == '$') - set_reg(sd, VariableCode::VARIABLE, reg.iplus(i), conv_str(st, &AARG(1))); + if (prefix == '.' && name[1] == '@') + set_scope_reg(st, reg.iplus(i), AARG(i)); + else if (postfix == '$') + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), conv_str(st, &AARG(1))); else - set_reg(sd, VariableCode::VARIABLE, reg.iplus(i), conv_num(st, &AARG(1))); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), conv_num(st, &AARG(1))); } } @@ -1045,7 +1132,7 @@ void builtin_getarraysize(ScriptState *st) ZString name = variable_names.outtern(reg.base()); char prefix = name.front(); - if (prefix != '$' && prefix != '@') + if (prefix != '$' && prefix != '@' && prefix != '.') { PRINTF("builtin_copyarray: illegal scope!\n"_fmt); return; @@ -2908,7 +2995,7 @@ void builtin_getpartnerid2(ScriptState *st) static void builtin_explode(ScriptState *st) { - dumb_ptr sd = nullptr; + dumb_ptr bl = nullptr; SIR reg = AARG(0).get_if()->reg; ZString name = variable_names.outtern(reg.base()); const char separator = conv_str(st, &AARG(2))[0]; @@ -2917,33 +3004,49 @@ void builtin_explode(ScriptState *st) char prefix = name.front(); char postfix = name.back(); - if (prefix != '$' && prefix != '@') + if (prefix != '$' && prefix != '@' && prefix != '.') { PRINTF("builtin_explode: illegal scope!\n"_fmt); return; } - if (prefix != '$') - sd = script_rid2sd(st); + if (prefix == '.' && name[1] != '@') + bl = map_id2bl(st->oid)->is_npc(); + else if (prefix != '$' && prefix != '.') + bl = map_id2bl(st->rid)->is_player(); for (int j = 0; j < 256; j++) { auto find = std::find(str.begin(), str.end(), separator); if (find == str.end()) { - if (postfix == '$') - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), str); + if (prefix == '.' && name[1] == '@') + { + struct script_data vd = script_data(ScriptDataInt{atoi(str.c_str())}); + if (postfix == '$') + vd = script_data(ScriptDataStr{str}); + set_scope_reg(st, reg.iplus(j), &vd); + } + else if (postfix == '$') + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), str); else - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), atoi(str.c_str())); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), atoi(str.c_str())); break; } { val = str.xislice_h(find); str = str.xislice_t(find + 1); - if (postfix == '$') - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), val); + if (prefix == '.' && name[1] == '@') + { + struct script_data vd = script_data(ScriptDataInt{atoi(val.c_str())}); + if (postfix == '$') + vd = script_data(ScriptDataStr{val}); + set_scope_reg(st, reg.iplus(j), &vd); + } + else if (postfix == '$') + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), val); else - set_reg(sd, VariableCode::VARIABLE, reg.iplus(j), atoi(val.c_str())); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), atoi(val.c_str())); } } } @@ -3149,6 +3252,102 @@ void builtin_specialeffect2(ScriptState *st) } +static +void builtin_get(ScriptState *st) +{ + BlockId id; + dumb_ptr bl = nullptr; + if (auto *u = AARG(0).get_if()) + { + SIR reg = u->reg; + struct script_data *sdata = &AARG(1); + get_val(st, sdata); + CharName name; + if (sdata->is()) + { + name = stringish(ZString(conv_str(st, sdata))); + if (name.to__actual()) + bl = map_nick2sd(name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + + if (bl == nullptr) + return; + int var = pc_readparam(bl->is_player(), reg.sp()); + push_int(st->stack, var); + return; + } + + struct script_data *sdata = &AARG(1); + get_val(st, sdata); + + SIR reg = AARG(0).get_if()->reg; + ZString name_ = variable_names.outtern(reg.base()); + char prefix = name_.front(); + char postfix = name_.back(); + + if(prefix == '.') + { + if (name_[1] == '@') + { + PRINTF("builtin_get: illegal scope!\n"_fmt); + return; + } + NpcName name; + if (sdata->is()) + { + name = stringish(ZString(conv_str(st, sdata))); + bl = npc_name2id(name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + } + else if(prefix != '$') + { + CharName name; + if (sdata->is()) + { + name = stringish(ZString(conv_str(st, sdata))); + if (name.to__actual()) + bl = map_nick2sd(name); + } + else + { + id = wrap(conv_num(st, sdata)); + bl = map_id2bl(id); + } + } + else + { + PRINTF("builtin_get: illegal scope !\n"_fmt); + return; + } + + if (!bl) + { + PRINTF("builtin_get: no block list attached !\n"_fmt); + return; + } + + if (postfix == '$') + { + ZString var = pc_readregstr(bl, reg); + push_str(st->stack, var); + } + else + { + int var = pc_readreg(bl, reg); + push_int(st->stack, var); + } +} + /*========================================== * Nude [Valaris] *------------------------------------------ @@ -3859,7 +4058,8 @@ BuiltinFunction builtin_functions[] = BUILTIN(if, "iF*"_s, '\0'), BUILTIN(elif, "iF*"_s, '\0'), BUILTIN(else, "F*"_s, '\0'), - BUILTIN(set, "Ne"_s, '\0'), + BUILTIN(set, "Ne?"_s, '\0'), + BUILTIN(get, "Ne"_s, '.'), BUILTIN(setarray, "Ne*"_s, '\0'), BUILTIN(cleararray, "Nei"_s, '\0'), BUILTIN(getarraysize, "N"_s, 'i'), @@ -3968,7 +4168,7 @@ BuiltinFunction builtin_functions[] = BUILTIN(aggravate, "Mxyxyi"_s, '\0'), BUILTIN(fakenpcname, "ssi"_s, '\0'), BUILTIN(puppet, "mxysi"_s, 'i'), - BUILTIN(destroypuppet, "?"_s, '\0'), + BUILTIN(destroy, "?"_s, '\0'), BUILTIN(getx, ""_s, 'i'), BUILTIN(gety, ""_s, 'i'), BUILTIN(getnpcx, "?"_s, 'i'), diff --git a/src/map/script-parse.cpp b/src/map/script-parse.cpp index a785748..a69df40 100644 --- a/src/map/script-parse.cpp +++ b/src/map/script-parse.cpp @@ -283,6 +283,10 @@ ZString::iterator skip_word(ZString::iterator p) p++; // MAP鯖内共有変数用 if (*p == '@') p++; // 一時的変数用(like weiss) + if (*p == '.') + p++; // npc + if (*p == '@') + p++; // scope if (*p == '#') p++; // account変数用 if (*p == '#') @@ -623,6 +627,7 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) "end"_s, "mapexit"_s, "shop"_s, + "destroy"_s, }; *can_step = terminators.count(cmd->strs) == 0; } -- cgit v1.2.3-60-g2f50