|
@@ -988,14 +988,14 @@ std::bitset<SCB_MAX> StatusDatabase::getCalcFlag(sc_type type) {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Get SC's END list
|
|
|
|
|
|
+ * Get SC's EndOnStart list
|
|
* @param sc: SC type
|
|
* @param sc: SC type
|
|
* @return End list
|
|
* @return End list
|
|
**/
|
|
**/
|
|
-std::vector<sc_type> StatusDatabase::getEnd(sc_type type) {
|
|
|
|
|
|
+std::vector<sc_type> StatusDatabase::getEndOnStart(sc_type type) {
|
|
std::shared_ptr<s_status_change_db> status = status_db.find(type);
|
|
std::shared_ptr<s_status_change_db> status = status_db.find(type);
|
|
|
|
|
|
- return status ? status->end : std::vector<sc_type> {};
|
|
|
|
|
|
+ return status ? status->endonstart : std::vector<sc_type> {};
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -10240,9 +10240,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
std::vector<sc_type> endlist;
|
|
std::vector<sc_type> endlist;
|
|
|
|
|
|
if (type == SC_BERSERK && val3 == SC__BLOODYLUST) //There is some reasons that using SC_BERSERK first before SC__BLOODYLUST itself on Akinari's fix
|
|
if (type == SC_BERSERK && val3 == SC__BLOODYLUST) //There is some reasons that using SC_BERSERK first before SC__BLOODYLUST itself on Akinari's fix
|
|
- endlist = status_db.getEnd(SC__BLOODYLUST);
|
|
|
|
|
|
+ endlist = status_db.getEndOnStart(SC__BLOODYLUST);
|
|
else
|
|
else
|
|
- endlist = scdb->end;
|
|
|
|
|
|
+ endlist = scdb->endonstart;
|
|
|
|
|
|
// End the SCs from the list
|
|
// End the SCs from the list
|
|
if (!endlist.empty()) {
|
|
if (!endlist.empty()) {
|
|
@@ -12513,7 +12513,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
- if (calc_flag.none() && scdb->skill_id == 0 && scdb->icon == EFST_BLANK && scdb->opt1 == OPT1_NONE && scdb->opt2 == OPT2_NONE && scdb->state.none() && scdb->flag.none() && scdb->end.empty() && scdb->endreturn.empty() && scdb->fail.empty()) {
|
|
|
|
|
|
+ if (calc_flag.none() && scdb->skill_id == 0 && scdb->icon == EFST_BLANK && scdb->opt1 == OPT1_NONE && scdb->opt2 == OPT2_NONE && scdb->state.none() && scdb->flag.none() && scdb->endonstart.empty() && scdb->endreturn.empty() && scdb->fail.empty() && scdb->endonend.empty()) {
|
|
// Status change with no calc, no icon, and no skill associated...?
|
|
// Status change with no calc, no icon, and no skill associated...?
|
|
ShowWarning("status_change_start: Status %s (%d) is bare. Add the NoWarning flag to suppress this message.\n", script_get_constant_str("SC_", type), type);
|
|
ShowWarning("status_change_start: Status %s (%d) is bare. Add the NoWarning flag to suppress this message.\n", script_get_constant_str("SC_", type), type);
|
|
return 0;
|
|
return 0;
|
|
@@ -13072,11 +13072,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
((TBL_MER*)d_bl)->devotion_flag = 0;
|
|
((TBL_MER*)d_bl)->devotion_flag = 0;
|
|
clif_devotion(d_bl, NULL);
|
|
clif_devotion(d_bl, NULL);
|
|
}
|
|
}
|
|
-
|
|
|
|
- status_change_end(bl, SC_AUTOGUARD);
|
|
|
|
- status_change_end(bl, SC_DEFENDER);
|
|
|
|
- status_change_end(bl, SC_REFLECTSHIELD);
|
|
|
|
- status_change_end(bl, SC_ENDURE);
|
|
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -13138,12 +13133,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
|
|
|
|
if((sce->val1&0xFFFF) == CG_MOONLIT)
|
|
if((sce->val1&0xFFFF) == CG_MOONLIT)
|
|
clif_status_change(bl,EFST_MOON,0,0,0,0,0);
|
|
clif_status_change(bl,EFST_MOON,0,0,0,0,0);
|
|
-
|
|
|
|
-#ifdef RENEWAL
|
|
|
|
- status_change_end(bl, SC_ENSEMBLEFATIGUE);
|
|
|
|
-#else
|
|
|
|
- status_change_end(bl, SC_LONGING);
|
|
|
|
-#endif
|
|
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case SC_NOCHAT:
|
|
case SC_NOCHAT:
|
|
@@ -13371,9 +13360,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
- case SC_TEARGAS:
|
|
|
|
- status_change_end(bl,SC_TEARGAS_SOB);
|
|
|
|
- break;
|
|
|
|
case SC_SITDOWN_FORCE:
|
|
case SC_SITDOWN_FORCE:
|
|
case SC_BANANA_BOMB_SITDOWN:
|
|
case SC_BANANA_BOMB_SITDOWN:
|
|
if( sd && pc_issit(sd) && pc_setstand(sd, false) )
|
|
if( sd && pc_issit(sd) && pc_setstand(sd, false) )
|
|
@@ -13387,25 +13373,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
calc_flag = status_db.getSCB_ALL(); // Required for overlapping
|
|
calc_flag = status_db.getSCB_ALL(); // Required for overlapping
|
|
break;
|
|
break;
|
|
|
|
|
|
- case SC_SUNSTANCE:
|
|
|
|
- status_change_end(bl, SC_LIGHTOFSUN);
|
|
|
|
- break;
|
|
|
|
- case SC_LUNARSTANCE:
|
|
|
|
- status_change_end(bl, SC_NEWMOON);
|
|
|
|
- status_change_end(bl, SC_LIGHTOFMOON);
|
|
|
|
- break;
|
|
|
|
- case SC_STARSTANCE:
|
|
|
|
- status_change_end(bl, SC_FALLINGSTAR);
|
|
|
|
- status_change_end(bl, SC_LIGHTOFSTAR);
|
|
|
|
- break;
|
|
|
|
- case SC_UNIVERSESTANCE:
|
|
|
|
- status_change_end(bl, SC_LIGHTOFSUN);
|
|
|
|
- status_change_end(bl, SC_NEWMOON);
|
|
|
|
- status_change_end(bl, SC_LIGHTOFMOON);
|
|
|
|
- status_change_end(bl, SC_FALLINGSTAR);
|
|
|
|
- status_change_end(bl, SC_LIGHTOFSTAR);
|
|
|
|
- status_change_end(bl, SC_DIMENSION);
|
|
|
|
- break;
|
|
|
|
case SC_GRAVITYCONTROL:
|
|
case SC_GRAVITYCONTROL:
|
|
status_fix_damage(bl, bl, sce->val2, clif_damage(bl, bl, gettick(), 0, 0, sce->val2, 0, DMG_NORMAL, 0, false), 0);
|
|
status_fix_damage(bl, bl, sce->val2, clif_damage(bl, bl, gettick(), 0, 0, sce->val2, 0, DMG_NORMAL, 0, false), 0);
|
|
clif_specialeffect(bl, 223, AREA);
|
|
clif_specialeffect(bl, 223, AREA);
|
|
@@ -13479,13 +13446,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
///< !CHECKME: Seems on official, there's delay before same target can be vacuumed in same area again [Cydh]
|
|
///< !CHECKME: Seems on official, there's delay before same target can be vacuumed in same area again [Cydh]
|
|
sc_start2(bl, bl, SC_VACUUM_EXTREME_POSTDELAY, 100, sce->val1, sce->val2, skill_get_time2(SO_VACUUM_EXTREME,sce->val1));
|
|
sc_start2(bl, bl, SC_VACUUM_EXTREME_POSTDELAY, 100, sce->val1, sce->val2, skill_get_time2(SO_VACUUM_EXTREME,sce->val1));
|
|
break;
|
|
break;
|
|
- case SC_SWORDCLAN:
|
|
|
|
- case SC_ARCWANDCLAN:
|
|
|
|
- case SC_GOLDENMACECLAN:
|
|
|
|
- case SC_CROSSBOWCLAN:
|
|
|
|
- case SC_JUMPINGCLAN:
|
|
|
|
- status_change_end(bl,SC_CLAN_INFO);
|
|
|
|
- break;
|
|
|
|
case SC_DIMENSION1:
|
|
case SC_DIMENSION1:
|
|
case SC_DIMENSION2:
|
|
case SC_DIMENSION2:
|
|
if (sd)
|
|
if (sd)
|
|
@@ -13523,9 +13483,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
pc_delservantball( *sd, sd->servantball );
|
|
pc_delservantball( *sd, sd->servantball );
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
- case SC_CHARGINGPIERCE:
|
|
|
|
- status_change_end(bl, SC_CHARGINGPIERCE_COUNT);
|
|
|
|
- break;
|
|
|
|
case SC_ABYSSFORCEWEAPON:
|
|
case SC_ABYSSFORCEWEAPON:
|
|
if( sd ){
|
|
if( sd ){
|
|
pc_delabyssball( *sd, sd->abyssball );
|
|
pc_delabyssball( *sd, sd->abyssball );
|
|
@@ -13533,6 +13490,13 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // End statuses found in the EndOnEnd list.
|
|
|
|
+ if (!scdb->endonend.empty()) {
|
|
|
|
+ for (const auto &it : scdb->endonend) {
|
|
|
|
+ status_change_end(bl, it);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
// Reset the options as needed
|
|
// Reset the options as needed
|
|
std::bitset<SCF_MAX> opt_flag = scdb->flag;
|
|
std::bitset<SCF_MAX> opt_flag = scdb->flag;
|
|
bool disable_opt_flag = false;
|
|
bool disable_opt_flag = false;
|
|
@@ -15651,8 +15615,8 @@ uint64 StatusDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (this->nodeExists(node, "End")) {
|
|
|
|
- const ryml::NodeRef& endNode = node["End"];
|
|
|
|
|
|
+ if (this->nodeExists(node, "EndOnStart")) {
|
|
|
|
+ const ryml::NodeRef& endNode = node["EndOnStart"];
|
|
|
|
|
|
for (const auto &it : endNode) {
|
|
for (const auto &it : endNode) {
|
|
std::string end;
|
|
std::string end;
|
|
@@ -15662,12 +15626,12 @@ uint64 StatusDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
int64 constant;
|
|
int64 constant;
|
|
|
|
|
|
if (!script_get_constant(end_constant.c_str(), &constant)) {
|
|
if (!script_get_constant(end_constant.c_str(), &constant)) {
|
|
- this->invalidWarning(endNode, "End status %s is invalid.\n", end.c_str());
|
|
|
|
|
|
+ this->invalidWarning(endNode, "EndOnStart status %s is invalid.\n", end.c_str());
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
if (!this->validateStatus(static_cast<sc_type>(constant))) {
|
|
if (!this->validateStatus(static_cast<sc_type>(constant))) {
|
|
- this->invalidWarning(endNode, "End status %s is out of bounds.\n", end.c_str());
|
|
|
|
|
|
+ this->invalidWarning(endNode, "EndOnStart status %s is out of bounds.\n", end.c_str());
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -15677,9 +15641,9 @@ uint64 StatusDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
if (active)
|
|
if (active)
|
|
- status->end.push_back(static_cast<sc_type>(constant));
|
|
|
|
|
|
+ status->endonstart.push_back(static_cast<sc_type>(constant));
|
|
else
|
|
else
|
|
- util::vector_erase_if_exists(status->end, static_cast<sc_type>(constant));
|
|
|
|
|
|
+ util::vector_erase_if_exists(status->endonstart, static_cast<sc_type>(constant));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -15715,6 +15679,38 @@ uint64 StatusDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (this->nodeExists(node, "EndOnEnd")) {
|
|
|
|
+ const ryml::NodeRef &endNode = node["EndOnEnd"];
|
|
|
|
+
|
|
|
|
+ for (const auto &it : endNode) {
|
|
|
|
+ std::string end;
|
|
|
|
+ c4::from_chars(it.key(), &end);
|
|
|
|
+
|
|
|
|
+ std::string end_constant = "SC_" + end;
|
|
|
|
+ int64 constant;
|
|
|
|
+
|
|
|
|
+ if (!script_get_constant(end_constant.c_str(), &constant)) {
|
|
|
|
+ this->invalidWarning(endNode, "EndOnEnd status %s is invalid.\n", end.c_str());
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!this->validateStatus(static_cast<sc_type>(constant))) {
|
|
|
|
+ this->invalidWarning(endNode, "EndOnEnd status %s is out of bounds.\n", end.c_str());
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool active;
|
|
|
|
+
|
|
|
|
+ if (!this->asBool(endNode, end, active))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (active)
|
|
|
|
+ status->endonend.push_back(static_cast<sc_type>(constant));
|
|
|
|
+ else
|
|
|
|
+ util::vector_erase_if_exists(status->endonend, static_cast<sc_type>(constant));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (!exists) {
|
|
if (!exists) {
|
|
this->put(status_id, status);
|
|
this->put(status_id, status);
|
|
}
|
|
}
|