summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/clif.c9
-rw-r--r--src/map/status.c264
-rw-r--r--src/map/status.h18
-rw-r--r--src/map/unit.c50
4 files changed, 114 insertions, 227 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index ed9eb1769..0ddc5f6ea 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10116,7 +10116,14 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd)
if (fitem == NULL || fitem->bl.type != BL_ITEM || fitem->bl.m != sd->bl.m)
break;
- if( sd->sc.cant.pickup )
+ if( sd->sc.count && (
+ sd->sc.data[SC_HIDING] ||
+ sd->sc.data[SC_CLOAKING] ||
+ sd->sc.data[SC_TRICKDEAD] ||
+ sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_CLOAKINGEXCEED] ||
+ (sd->sc.data[SC_NOCHAT] &&sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
+ ) )
break;
if (pc_cant_act(sd))
diff --git a/src/map/status.c b/src/map/status.c
index 79579fe05..64f7f81af 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -83,7 +83,6 @@ static int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is
static unsigned int StatusChangeFlagTable[SC_MAX]; // status -> flags
static int StatusSkillChangeTable[SC_MAX]; // status -> skill
static int StatusRelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif_status_change to identify for which bl types to send packets)
-static unsigned int StatusChangeStateTable[SC_MAX]; // status -> flags
/**
@@ -185,7 +184,6 @@ void initChangeTables(void) {
memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable));
memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable));
- memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable));
//First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex]
@@ -994,66 +992,6 @@ void initChangeTables(void) {
if( !battle_config.display_hallucination ) //Disable Hallucination.
StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK;
-
- /* StatusChangeState (SCS_) NOMOVE */
- StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_BLADESTOP_WAIT] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_GOSPEL] |= SCS_NOMOVE|SCS_NOMOVECOND;
- StatusChangeStateTable[SC_BASILICA] |= SCS_NOMOVE|SCS_NOMOVECOND;
- StatusChangeStateTable[SC_STOP] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CLOSECONFINE] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CLOSECONFINE2] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_MADNESSCANCEL] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_GRAVITATION] |= SCS_NOMOVE|SCS_NOMOVECOND;
- StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_ELECTRICSHOCKER] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_BITE] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_THORNSTRAP] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_MAGNETICFIELD] |= SCS_NOMOVE;
- StatusChangeStateTable[SC__MANHOLE] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND;
- StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND;
- StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_KAGEHUMI] |= SCS_NOMOVE;
- StatusChangeStateTable[SC_KYOUGAKU] |= SCS_NOMOVE;
-
- /* StatusChangeState (SCS_) NOPICKUPITEMS */
- StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM;
- StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM;
- StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOPICKITEM;
- StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOPICKITEM;
- StatusChangeStateTable[SC_CLOAKINGEXCEED] |= SCS_NOPICKITEM;
- StatusChangeStateTable[SC_NOCHAT] |= SCS_NOPICKITEM|SCS_NOPICKITEMCOND;
-
- /* StatusChangeState (SCS_) NODROPITEMS */
- StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NODROPITEM;
- StatusChangeStateTable[SC_BLADESTOP] |= SCS_NODROPITEM;
- StatusChangeStateTable[SC_NOCHAT] |= SCS_NODROPITEM|SCS_NODROPITEMCOND;
-
- /* StatusChangeState (SCS_) NOCAST (skills) */
- StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST;
- StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST;
- StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST;
- StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST;
- StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST;
- StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST;
- StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST;
- StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST|SCS_NOCASTCOND;
- StatusChangeStateTable[SC__IGNORANCE] |= SCS_NOCAST;
- StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCAST;
- StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCAST;
- StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST;
- StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST;
-
- //Homon S
- StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE;
-
}
static void initDummyData(void)
@@ -1646,7 +1584,18 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
(src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)
) { //Skills blocked through status changes...
if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
- sc->cant.cast ||
+ sc->data[SC_SILENCE] ||
+ sc->data[SC_STEELBODY] ||
+ sc->data[SC_BERSERK] ||
+ sc->data[SC__BLOODYLUST] ||
+ sc->data[SC_OBLIVIONCURSE] ||
+ sc->data[SC_WHITEIMPRISON] ||
+ sc->data[SC__INVISIBILITY] ||
+ (sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) ||
+ sc->data[SC__IGNORANCE] ||
+ sc->data[SC_DEEPSLEEP] ||
+ sc->data[SC_SATURDAYNIGHTFEVER] ||
+ sc->data[SC_CURSEDCIRCLE_TARGET] ||
(sc->data[SC_MARIONETTE] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it
(sc->data[SC_MARIONETTE2] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another
(sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) ||
@@ -3500,63 +3449,6 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
regen->rate.hp *= 2;
}
-void status_calc_state( struct block_list *bl, struct status_change *sc, enum scs_flag flag, bool start ) {
-
- /* no sc at all, we can zero without any extra weight over our conciousness */
- if( !sc->count ) {
- memset(&sc->cant, 0, sizeof (sc->cant));
- return;
- }
-
- /* can move? */
- if( flag&SCS_NOMOVE ) {
- if( !(flag&SCS_NOMOVECOND) ) {
- sc->cant.move += ( start ? 1 : -1 );
- } else if(
- (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect
- || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
- || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
- || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
- || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3
- && !(sc->data[SC_CAMOUFLAGE]->val3&1))
- ) {
- sc->cant.move += ( start ? 1 : -1 );
- }
- }
-
- /* can't use skills */
- if( flag&SCS_NOCAST ) {
- if( !(flag&SCS_NOCASTCOND) ) {
- sc->cant.cast += ( start ? 1 : -1 );
- } else if( (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) ){
- sc->cant.cast += ( start ? 1 : -1 );
- }
- }
-
- /* player-only states */
- if( bl->type == BL_PC ) {
-
- /* can pick items? */
- if( flag&SCS_NOPICKITEM ) {
- if( !(flag&SCS_NOPICKITEMCOND) ) {
- sc->cant.pickup += ( start ? 1 : -1 );
- } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) {
- sc->cant.pickup += ( start ? 1 : -1 );
- }
- }
-
- /* can drop items? */
- if( flag&SCS_NODROPITEM ) {
- if( !(flag&SCS_NODROPITEMCOND) ) {
- sc->cant.drop += ( start ? 1 : -1 );
- } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) {
- sc->cant.drop += ( start ? 1 : -1 );
- }
- }
- }
-
- return;
-}
/// Recalculates parts of an object's battle status according to the specified flags.
/// @param flag bitfield of values from enum scb_flag
void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
@@ -6430,7 +6322,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
struct status_data *status;
struct view_data *vd;
int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0;
- bool sc_isnew = true;
nullpo_ret(bl);
sc = status_get_sc(bl);
@@ -8866,7 +8757,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if((sce=sc->data[type])) {// reuse old sc
if( sce->timer != INVALID_TIMER )
delete_timer(sce->timer, status_change_timer);
- sc_isnew = false;
} else {// new sc
++(sc->count);
sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry);
@@ -8883,10 +8773,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if (calc_flag)
status_calc_bl(bl,calc_flag);
- if ( sc_isnew && StatusChangeStateTable[type] ) /* non-zero */
- status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true);
-
-
if(sd && sd->pd)
pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing
@@ -8984,8 +8870,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
* 2 - Do clif
* 3 - Do not remove some permanent/time-independent effects
*------------------------------------------*/
-int status_change_clear(struct block_list* bl, int type)
-{
+int status_change_clear(struct block_list* bl, int type) {
struct status_change* sc;
int i;
@@ -8994,69 +8879,64 @@ int status_change_clear(struct block_list* bl, int type)
if (!sc || !sc->count)
return 0;
- for(i = 0; i < SC_MAX; i++)
- {
+ for(i = 0; i < SC_MAX; i++) {
if(!sc->data[i])
continue;
if(type == 0)
- switch (i)
- { //Type 0: PC killed -> Place here statuses that do not dispel on death.
- case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death
- if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK )
- break;
- case SC_WEIGHT50:
- case SC_WEIGHT90:
- case SC_EDP:
- case SC_MELTDOWN:
- case SC_XMAS:
- case SC_SUMMER:
- case SC_NOCHAT:
- case SC_FUSION:
- case SC_EARTHSCROLL:
- case SC_READYSTORM:
- case SC_READYDOWN:
- case SC_READYCOUNTER:
- case SC_READYTURN:
- case SC_DODGE:
- case SC_JAILED:
- case SC_EXPBOOST:
- case SC_ITEMBOOST:
- case SC_HELLPOWER:
- case SC_JEXPBOOST:
- case SC_AUTOTRADE:
- case SC_WHISTLE:
- case SC_ASSNCROS:
- case SC_POEMBRAGI:
- case SC_APPLEIDUN:
- case SC_HUMMING:
- case SC_DONTFORGETME:
- case SC_FORTUNE:
- case SC_SERVICE4U:
- case SC_FOOD_STR_CASH:
- case SC_FOOD_AGI_CASH:
- case SC_FOOD_VIT_CASH:
- case SC_FOOD_DEX_CASH:
- case SC_FOOD_INT_CASH:
- case SC_FOOD_LUK_CASH:
- case SC_DEF_RATE:
- case SC_MDEF_RATE:
- case SC_INCHEALRATE:
- case SC_INCFLEE2:
- case SC_INCHIT:
- case SC_ATKPOTION:
- case SC_MATKPOTION:
- case SC_S_LIFEPOTION:
- case SC_L_LIFEPOTION:
- case SC_PUSH_CART:
- continue;
-
+ switch (i) { //Type 0: PC killed -> Place here statuses that do not dispel on death.
+ case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death
+ if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK )
+ break;
+ case SC_WEIGHT50:
+ case SC_WEIGHT90:
+ case SC_EDP:
+ case SC_MELTDOWN:
+ case SC_XMAS:
+ case SC_SUMMER:
+ case SC_NOCHAT:
+ case SC_FUSION:
+ case SC_EARTHSCROLL:
+ case SC_READYSTORM:
+ case SC_READYDOWN:
+ case SC_READYCOUNTER:
+ case SC_READYTURN:
+ case SC_DODGE:
+ case SC_JAILED:
+ case SC_EXPBOOST:
+ case SC_ITEMBOOST:
+ case SC_HELLPOWER:
+ case SC_JEXPBOOST:
+ case SC_AUTOTRADE:
+ case SC_WHISTLE:
+ case SC_ASSNCROS:
+ case SC_POEMBRAGI:
+ case SC_APPLEIDUN:
+ case SC_HUMMING:
+ case SC_DONTFORGETME:
+ case SC_FORTUNE:
+ case SC_SERVICE4U:
+ case SC_FOOD_STR_CASH:
+ case SC_FOOD_AGI_CASH:
+ case SC_FOOD_VIT_CASH:
+ case SC_FOOD_DEX_CASH:
+ case SC_FOOD_INT_CASH:
+ case SC_FOOD_LUK_CASH:
+ case SC_DEF_RATE:
+ case SC_MDEF_RATE:
+ case SC_INCHEALRATE:
+ case SC_INCFLEE2:
+ case SC_INCHIT:
+ case SC_ATKPOTION:
+ case SC_MATKPOTION:
+ case SC_S_LIFEPOTION:
+ case SC_L_LIFEPOTION:
+ case SC_PUSH_CART:
+ continue;
}
- if( type == 3 )
- {
- switch (i)
- {// TODO: This list may be incomplete
+ if( type == 3 ) {
+ switch (i) {// TODO: This list may be incomplete
case SC_WEIGHT50:
case SC_WEIGHT90:
case SC_NOCHAT:
@@ -9067,8 +8947,8 @@ int status_change_clear(struct block_list* bl, int type)
status_change_end(bl, (sc_type)i, INVALID_TIMER);
- if( type == 1 && sc->data[i] )
- { //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
+ if( type == 1 && sc->data[i] ) {
+ //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
(sc->count)--;
if (sc->data[i]->timer != INVALID_TIMER)
delete_timer(sc->data[i]->timer, status_change_timer);
@@ -9142,9 +9022,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
(sc->count)--;
- if ( StatusChangeStateTable[type] )
- status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],false);
-
sc->data[type] = NULL;
vd = status_get_viewdata(bl);
@@ -9571,9 +9448,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
}
break;
- case SC_VACUUM_EXTREME:
- if(sc && sc->cant.move > 0) sc->cant.move--;
- break;
case SC_KYOUGAKU:
clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash
clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0);
@@ -10385,10 +10259,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
break;
case SC_VACUUM_EXTREME:
if( --(sce->val4) >= 0 ){
- if( !unit_is_walking(bl) && !sce->val2 ){
- sc->cant.move++;
- sce->val2 = 1;
- }
sc_timer_next(100 + tick, status_change_timer, bl->id, data);
return 0;
}
diff --git a/src/map/status.h b/src/map/status.h
index 44012566f..4535b1aed 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -1501,18 +1501,6 @@ enum manner_flags
MANNER_NOROOM = 0x10,
};
-/* Status Change State Flags */
-enum scs_flag {
- SCS_NOMOVECOND = 0x00000001, /* cond flag for nomove */
- SCS_NOMOVE = 0x00000002, /* unit unable to move */
- SCS_NOPICKITEMCOND = 0x00000004, /* cond flag for nopickitem */
- SCS_NOPICKITEM = 0x00000008, /* player unable to pick up items */
- SCS_NODROPITEMCOND = 0x00000010, /* cond flag for nodropitem */
- SCS_NODROPITEM = 0x00000020, /* player unable to drop items */
- SCS_NOCASTCOND = 0x00000040, /* cond flag for nocast */
- SCS_NOCAST = 0x00000080, /* unit unable to cast skills */
-};
-
//Define flags for the status_calc_bl function. [Skotlex]
enum scb_flag
{
@@ -1662,12 +1650,6 @@ struct status_change {
unsigned char count;
//TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive.
unsigned char jb_flag; //Joint Beat type flag
- struct {
- unsigned char move;
- unsigned char pickup;
- unsigned char drop;
- unsigned char cast;
- } cant;/* status change state flags */
//int sg_id; //ID of the previous Storm gust that hit you
short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point
/**
diff --git a/src/map/unit.c b/src/map/unit.c
index c9d6ab165..11f7cb8c8 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -921,17 +921,45 @@ int unit_can_move(struct block_list *bl) {
return 0; //Can't move
if (sc) {
- if( sc->cant.move /* status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability */
- || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
- || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
- || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && (
- !sc->data[SC_LONGING] ||
- (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
- (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
- ) )
- || (sc->data[SC_CLOAKING] && //Need wall at level 1-2
- sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
- )
+ if( sc->count && (
+ sc->data[SC_ANKLE]
+ || sc->data[SC_AUTOCOUNTER]
+ || sc->data[SC_TRICKDEAD]
+ || sc->data[SC_BLADESTOP]
+ || sc->data[SC_BLADESTOP_WAIT]
+ || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect
+ || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
+ || sc->data[SC_STOP]
+ || sc->data[SC_CLOSECONFINE]
+ || sc->data[SC_CLOSECONFINE2]
+ || sc->data[SC_MADNESSCANCEL]
+ || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
+ || sc->data[SC_WHITEIMPRISON]
+ || sc->data[SC_ELECTRICSHOCKER]
+ || sc->data[SC_BITE]
+ || sc->data[SC_THORNSTRAP]
+ || sc->data[SC_MAGNETICFIELD]
+ || sc->data[SC__MANHOLE]
+ || sc->data[SC_CURSEDCIRCLE_ATKER]
+ || sc->data[SC_CURSEDCIRCLE_TARGET]
+ || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
+ || sc->data[SC_NETHERWORLD]
+ || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1))
+ || sc->data[SC_MEIKYOUSISUI]
+ || sc->data[SC_KAGEHUMI]
+ || sc->data[SC_KYOUGAKU]
+ || sc->data[SC_PARALYSIS]
+ || sc->data[SC_VACUUM_EXTREME]
+ || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
+ || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
+ || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && (
+ !sc->data[SC_LONGING] ||
+ (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
+ (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
+ ) )
+ || (sc->data[SC_CLOAKING] && //Need wall at level 1-2
+ sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
+ ) )
return 0;