public bool KnockObjectBack(Actor a,List<Tile> line,int knockback_strength,Actor damage_source) { if(knockback_strength == 0){ //note that TURN_INTO_CORPSE should be set for 'a' - therefore it won't be removed and we can do what we want with it. return a.CollideWith(a.tile()); } int i=0; while(true){ Tile t = line[i]; if(t.actor() == a){ break; } ++i; } line.RemoveRange(0,i+1); if(line.Count == 0){ return a.CollideWith(a.tile()); } bool immobile = a.MovementPrevented(line[0]); string knocked_back_message = ""; if(!a.HasAttr(AttrType.TELEKINETICALLY_THROWN,AttrType.SELF_TK_NO_DAMAGE) && !immobile && player.CanSee(a)){ //if the player can see it now, don't check CanSee later. knocked_back_message = a.YouAre() + " knocked back. "; //B.Add(a.YouAre() + " knocked back. ",a); } int dice = 1; int damage_dice_to_other = 1; if(a.HasAttr(AttrType.TELEKINETICALLY_THROWN)){ dice = 3; damage_dice_to_other = 3; } if(a.HasAttr(AttrType.SELF_TK_NO_DAMAGE)){ dice = 0; } if(a.type == ActorType.SPORE_POD){ dice = 0; damage_dice_to_other = 0; } while(knockback_strength > 1){ //if the knockback strength is greater than 1, you're passing *over* at least one tile. Tile t = line[0]; line.RemoveAt(0); immobile = a.MovementPrevented(t); if(immobile){ if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked about. ",a); } if(a.type == ActorType.SPORE_POD){ return true; } return a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"crashing into the floor"); } if(!t.passable){ string deathstringname = t.AName(false); if(t.Is(TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR) && !a.HasAttr(AttrType.SMALL)){ string tilename = t.TheName(true); if(t.type == TileType.HIDDEN_DOOR){ tilename = "a hidden door"; t.Toggle(null); } if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked through " + tilename + ". ",a,t); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; //knockback_strength -= 2; //removing the distance modification for now t.Toggle(null); a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname); a.Move(t.row,t.col); if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ if(a.type == ActorType.HOMUNCULUS){ if(R.CoinFlip()){ t.AddFeature(FeatureType.OIL); } } else{ if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){ t.color = a.BloodColor(); } } } } else{ if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked into " + t.TheName(true) + ". ",a,t); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; if(a.type != ActorType.SPORE_POD){ Color blood = a.BloodColor(); if(blood != Color.Black && R.CoinFlip() && t.Is(TileType.WALL) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ t.color = blood; } a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname); } if(!a.HasAttr(AttrType.SMALL)){ t.Bump(a.DirectionOf(t)); } a.CollideWith(a.tile()); return !a.HasAttr(AttrType.CORPSE); } } else{ if(t.actor() != null){ if(player.CanSee(a.tile()) || player.CanSee(t)){ B.Add(a.YouVisibleAre() + " knocked into " + t.actor().TheName(true) + ". ",a,t.actor()); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; string actorname = t.actor().AName(false); string actorname2 = a.AName(false); if(t.actor().type != ActorType.SPORE_POD && !t.actor().HasAttr(AttrType.SELF_TK_NO_DAMAGE)){ t.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(damage_dice_to_other,6),damage_source,"colliding with " + actorname2); } if(a.type != ActorType.SPORE_POD){ a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"colliding with " + actorname); } a.CollideWith(a.tile()); return !a.HasAttr(AttrType.CORPSE); } else{ if(t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SMALL)){ t.RemoveFeature(FeatureType.WEB); } a.Move(t.row,t.col,false); if(t.Is(FeatureType.WEB) && a.HasAttr(AttrType.SMALL) && !a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED,AttrType.BURNING)){ knockback_strength = 0; } if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ if(a.type == ActorType.HOMUNCULUS){ if(R.CoinFlip()){ t.AddFeature(FeatureType.OIL); } } else{ if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){ t.color = a.BloodColor(); } } } } } M.Draw(); knockback_strength--; } if(knockback_strength < 1){ return !a.HasAttr(AttrType.CORPSE); } bool slip = false; int extra_slip_tiles = -1; bool slip_message_printed = false; do{ Tile t = line[0]; line.RemoveAt(0); immobile = a.MovementPrevented(t); if(immobile){ if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked about. ",a); } if(a.type == ActorType.SPORE_POD){ return true; } return a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"crashing into the floor"); } if(!t.passable){ string deathstringname = t.AName(false); if(t.Is(TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR) && !a.HasAttr(AttrType.SMALL)){ string tilename = t.TheName(true); if(t.type == TileType.HIDDEN_DOOR){ tilename = "a hidden door"; t.Toggle(null); } if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked through " + tilename + ". ",a,t); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; t.Toggle(null); a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname); a.Move(t.row,t.col); if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ if(a.type == ActorType.HOMUNCULUS){ if(R.CoinFlip()){ t.AddFeature(FeatureType.OIL); } } else{ if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){ t.color = a.BloodColor(); } } } return !a.HasAttr(AttrType.CORPSE); } else{ if(player.CanSee(a.tile())){ B.Add(a.YouVisibleAre() + " knocked into " + t.TheName(true) + ". ",a,t); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; if(a.type != ActorType.SPORE_POD){ Color blood = a.BloodColor(); if(blood != Color.Black && R.CoinFlip() && t.Is(TileType.WALL) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ t.color = blood; } a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname); } if(!a.HasAttr(AttrType.SMALL)){ t.Bump(a.DirectionOf(t)); } a.CollideWith(a.tile()); return !a.HasAttr(AttrType.CORPSE); } } else{ if(t.actor() != null){ if(player.CanSee(a.tile()) || player.CanSee(t)){ B.Add(a.YouVisibleAre() + " knocked into " + t.actor().TheName(true) + ". ",a,t.actor()); } else{ B.Add(knocked_back_message); } knocked_back_message = ""; string actorname = t.actor().AName(false); string actorname2 = a.AName(false); if(t.actor().type != ActorType.SPORE_POD && !t.actor().HasAttr(AttrType.SELF_TK_NO_DAMAGE)){ t.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(damage_dice_to_other,6),damage_source,"colliding with " + actorname2); } if(a.type != ActorType.SPORE_POD){ a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"colliding with " + actorname); } a.CollideWith(a.tile()); return !a.HasAttr(AttrType.CORPSE); } else{ slip = false; if(t.IsSlippery()){ B.Add(knocked_back_message); knocked_back_message = ""; slip = true; if(!slip_message_printed){ slip_message_printed = true; B.Add(a.You("slide") + "! "); } } else{ if(extra_slip_tiles > 0){ extra_slip_tiles--; } if(extra_slip_tiles == -1 && a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED) && !t.IsWater()){ B.Add(knocked_back_message); knocked_back_message = ""; extra_slip_tiles = 2; if(!slip_message_printed){ slip_message_printed = true; B.Add(a.You("slide") + "! "); } } } /*if(extra_slip_tiles > 0){ extra_slip_tiles--; } if(t.IsSlippery()){ B.Add(knocked_back_message); knocked_back_message = ""; slip = true; if(!slip_message_printed){ slip_message_printed = true; B.Add(a.You("slide") + "! "); } } else{ if(extra_slip_tiles == -1 && a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED)){ B.Add(knocked_back_message); knocked_back_message = ""; extra_slip_tiles = 2; if(!slip_message_printed){ slip_message_printed = true; B.Add(a.You("slide") + "! "); } } }*/ bool interrupted = false; if(t.inv != null && t.inv.type == ConsumableType.DETONATION){ //this will cause a new knockback effect and end the current one B.Add(knocked_back_message); knocked_back_message = ""; interrupted = true; } if(t.IsTrap()){ if(t.type == TileType.FLING_TRAP){ //otherwise you'd teleport around, continuing to slide from your previous position. interrupted = true; } B.Add(knocked_back_message); knocked_back_message = ""; } if(t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SMALL)){ t.RemoveFeature(FeatureType.WEB); } a.Move(t.row,t.col); if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){ if(a.type == ActorType.HOMUNCULUS){ if(R.CoinFlip()){ t.AddFeature(FeatureType.OIL); } } else{ if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){ t.color = a.BloodColor(); } } } if(a.HasAttr(AttrType.FROZEN)){ interrupted = true; } if(a.HasAttr(AttrType.SMALL) && t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED,AttrType.BURNING)){ B.Add(knocked_back_message); interrupted = true; } else{ if(a.tile().IsWater()){ interrupted = true; } B.Add(knocked_back_message); a.CollideWith(a.tile()); } knocked_back_message = ""; if(interrupted){ return !a.HasAttr(AttrType.CORPSE); } } } M.Draw(); } while(slip || extra_slip_tiles > 0); if(knocked_back_message != ""){ B.Add(knocked_back_message); //this probably never happens } return !a.HasAttr(AttrType.CORPSE); }