示例#1
0
 public static bool Telekinesis(bool cast,Actor user,Tile t)
 {
     bool wand = !cast;
     if(t == null){
         return false;
     }
     if(t != null){
         if(wand && user == player && !Item.identified[ConsumableType.TELEKINESIS]){
             Item.identified[ConsumableType.TELEKINESIS] = true;
             B.Add("(It was a wand of telekinesis!) ");
             B.PrintAll();
         }
         List<Tile> ai_line = null;
         if(user != player && t == player.tile()){
             var fires = user.TilesWithinDistance(12).Where(x=>x.passable && x.actor() == null && x.Is(FeatureType.FIRE) && user.CanSee(x) && player.HasBresenhamLineWithCondition(x,false,y=>y.passable && y.actor() == null));
             if(fires.Count > 0){
                 ai_line = player.GetBestExtendedLineOfEffect(fires.Random());
             }
             else{
                 if(wand){
                     ai_line = player.GetBestExtendedLineOfEffect(user);
                 }
                 else{
                     ai_line = player.GetBestExtendedLineOfEffect(player.TileInDirection(Global.RandomDirection()));
                 }
             }
         }
         Actor a = t.actor();
         if(a == null && t.inv == null && !t.Is(FeatureType.GRENADE) && t.Is(FeatureType.TROLL_CORPSE,FeatureType.TROLL_BLOODWITCH_CORPSE)){
             ActorType troll_type = t.Is(FeatureType.TROLL_CORPSE)? ActorType.TROLL : ActorType.TROLL_BLOODWITCH;
             FeatureType troll_corpse = t.Is(FeatureType.TROLL_CORPSE)? FeatureType.TROLL_CORPSE : FeatureType.TROLL_BLOODWITCH_CORPSE;
             Event troll_event = Q.FindTargetedEvent(t,EventType.REGENERATING_FROM_DEATH);
             troll_event.dead = true;
             Actor troll = Actor.Create(troll_type,t.row,t.col);
             foreach(Event e in Q.list){
                 if(e.target == troll && e.type == EventType.MOVE){
                     e.tiebreaker = troll_event.tiebreaker;
                     e.dead = true;
                     break;
                 }
             }
             Actor.tiebreakers[troll_event.tiebreaker] = troll;
             troll.symbol = '%';
             troll.attrs[AttrType.CORPSE] = 1;
             troll.SetName(troll.name + "'s corpse");
             troll.curhp = troll_event.value;
             troll.attrs[AttrType.PERMANENT_DAMAGE] = troll_event.secondary_value;
             troll.attrs[AttrType.NO_ITEM]++;
             t.features.Remove(troll_corpse);
             a = troll;
         }
         if(a != null){
             string msg = "Throw " + a.TheName(true) + " in which direction? ";
             if(a == player){
                 msg = "Throw yourself in which direction? ";
             }
             List<Tile> line = null;
             if(user == player){
                 TargetInfo info = a.GetTarget(false,12,0,false,true,false,msg);
                 if(info != null){
                     line = info.extended_line;
                 }
             }
             else{
                 line = ai_line;
             }
             if(line != null){
                 if(line.Count == 1 && line[0].actor() == user){
                     if(wand){
                         return true;
                     }
                     return false;
                 }
                 if(cast){
                     B.Add(user.You("cast") + " telekinesis. ",user);
                     if(a.type == ActorType.ALASI_BATTLEMAGE && !a.HasSpell(SpellType.TELEKINESIS)){
                         a.curmp += Spell.Tier(SpellType.TELEKINESIS);
                         if(a.curmp > a.maxmp){
                             a.curmp = a.maxmp;
                         }
                         a.GainSpell(SpellType.TELEKINESIS);
                         B.Add("Runes on " + a.Your() + " armor align themselves with the spell. ",a);
                     }
                 }
                 if(a == user && a == player){
                     B.Add("You throw yourself forward. ");
                 }
                 else{
                     if(line.Count == 1){
                         B.Add(user.YouVisible("throw") + " " + a.TheName(true) + " into the ceiling. ",user,a);
                     }
                     else{
                         B.Add(user.YouVisible("throw") + " " + a.TheName(true) + ". ",user,a);
                     }
                 }
                 B.DisplayNow();
                 user.attrs[AttrType.SELF_TK_NO_DAMAGE] = 1;
                 a.attrs[AttrType.TELEKINETICALLY_THROWN] = 1;
                 a.attrs[AttrType.TURN_INTO_CORPSE]++;
                 if(line.Count == 1){
                     a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(3,6),user,"colliding with the ceiling");
                     a.CollideWith(a.tile());
                 }
                 else{
                     a.tile().KnockObjectBack(a,line,12,user);
                 }
                 a.attrs[AttrType.TELEKINETICALLY_THROWN] = 0;
                 user.attrs[AttrType.SELF_TK_NO_DAMAGE] = 0;
                 if(a.curhp <= 0 && a.HasAttr(AttrType.REGENERATES_FROM_DEATH)){
                     a.attrs[AttrType.TURN_INTO_CORPSE] = 0;
                     a.attrs[AttrType.CORPSE] = 0;
                     a.attrs[AttrType.FROZEN] = 0;
                     a.attrs[AttrType.INVULNERABLE] = 0;
                     a.attrs[AttrType.SHIELDED] = 0;
                     a.attrs[AttrType.BLOCKING] = 0;
                     a.curhp = 1; //this is all pretty hacky - perhaps I should relocate the regenerating corpse through other means.
                     a.TakeDamage(DamageType.NORMAL,DamageClass.NO_TYPE,500,null);
                 }
                 else{
                     a.CorpseCleanup();
                 }
             }
             else{
                 if(wand){
                     return true;
                 }
                 return false;
             }
         }
         else{
             bool blast_fungus = false;
             if(t.type == TileType.BLAST_FUNGUS && !t.Is(FeatureType.GRENADE,FeatureType.WEB,FeatureType.FORASECT_EGG,FeatureType.BONES)){
                 blast_fungus = true;
             }
             if(t.inv != null || blast_fungus){
                 Item i = t.inv;
                 string itemname = "";
                 if(blast_fungus){
                     itemname = "the blast fungus";
                 }
                 else{
                     itemname = i.TheName(true);
                     if(i.quantity > 1){
                         itemname = "the " + i.SingularName();
                     }
                 }
                 string msg = "Throw " + itemname + " in which direction? ";
                 List<Tile> line = null;
                 if(user == player){
                     TargetInfo info = t.GetTarget(false,12,0,false,true,false,msg);
                     if(info != null){
                         line = info.extended_line;
                     }
                 }
                 else{
                     line = ai_line;
                 }
                 if(line != null){
                     if(line.Count > 13){
                         line = line.ToCount(13); //for range 12
                     }
                     if(cast){
                         B.Add(user.You("cast") + " telekinesis. ",user);
                     }
                     if(blast_fungus){
                         B.Add("The blast fungus is pulled from the floor. ",t);
                         B.Add("Its fuse ignites! ",t);
                         t.Toggle(null);
                         i = Item.Create(ConsumableType.BLAST_FUNGUS,t.row,t.col);
                         if(i != null){
                             i.other_data = 3;
                             i.revealed_by_light = true;
                             Q.Add(new Event(i,100,EventType.BLAST_FUNGUS));
                             Screen.AnimateMapCell(t.row,t.col,new colorchar('3',Color.Red),100);
                         }
                     }
                     if(line.Count == 1){
                         B.Add(user.YouVisible("throw") + " " + itemname + " into the ceiling. ",user,t);
                     }
                     else{
                         B.Add(user.YouVisible("throw") + " " + itemname + ". ",user,t);
                     }
                     B.DisplayNow();
                     if(i.quantity > 1){
                         i.quantity--;
                         bool revealed = i.revealed_by_light;
                         i = new Item(i,-1,-1);
                         i.revealed_by_light = revealed;
                     }
                     else{
                         t.inv = null;
                         Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col));
                     }
                     bool trigger_traps = false;
                     Tile t2 = line.LastBeforeSolidTile();
                     Actor first = user.FirstActorInLine(line);
                     if(t2 == line.LastOrDefault() && first == null){
                         trigger_traps = true;
                     }
                     if(first != null){
                         t2 = first.tile();
                     }
                     line = line.ToFirstSolidTileOrActor();
                     //if(line.Count > 0){
                     //	line.RemoveAt(line.Count - 1);
                     //}
                     if(line.Count > 0){
                         line.RemoveAt(line.Count - 1);
                     }
                     {
                         Tile first_unseen = null;
                         foreach(Tile tile2 in line){
                             if(!tile2.seen){
                                 first_unseen = tile2;
                                 break;
                             }
                         }
                         if(first_unseen != null){
                             line = line.To(first_unseen);
                             if(line.Count > 0){
                                 line.RemoveAt(line.Count - 1);
                             }
                         }
                     }
                     if(line.Count > 0){ //or > 1 ?
                         user.AnimateProjectile(line,i.symbol,i.color);
                     }
                     if(first == user){
                         B.Add(user.You("catch",true) + " it! ",user);
                         if(user.inv.Count < Global.MAX_INVENTORY_SIZE){
                             user.GetItem(i);
                         }
                         else{
                             B.Add("Your pack is too full to fit anything else. ");
                             i.ignored = true;
                             user.tile().GetItem(i);
                         }
                     }
                     else{
                         if(first != null){
                             B.Add("It hits " + first.the_name + ". ",first);
                         }
                         if(i.IsBreakable()){
                             if(i.quantity > 1){
                                 B.Add(i.TheName(true) + " break! ",t2);
                             }
                             else{
                                 B.Add(i.TheName(true) + " breaks! ",t2);
                             }
                             if(i.NameOfItemType() == "orb"){
                                 i.Use(null,new List<Tile>{t2});
                             }
                             else{
                                 i.CheckForMimic();
                             }
                         }
                         else{
                             t2.GetItem(i);
                         }
                         t2.MakeNoise(2);
                     }
                     if(first != null && first != user && first != player){
                         first.player_visibility_duration = -1;
                         first.attrs[AttrType.PLAYER_NOTICED]++;
                     }
                     else{
                         if(trigger_traps && t2.IsTrap()){
                             t2.TriggerTrap();
                         }
                     }
                 }
                 else{
                     if(wand){
                         return true;
                     }
                     return false;
                 }
             }
             else{
                 if(!t.Is(FeatureType.GRENADE) && (t.Is(TileType.DOOR_C,TileType.DOOR_O,TileType.POISON_BULB) || t.Is(FeatureType.WEB,FeatureType.FORASECT_EGG,FeatureType.BONES))){
                     if(cast){
                         B.Add(user.You("cast") + " telekinesis. ",user);
                     }
                     if(t.Is(TileType.DOOR_C)){
                         B.Add("The door slams open. ",t);
                         t.Toggle(null);
                     }
                     else{
                         if(t.Is(TileType.DOOR_O)){
                             B.Add("The door slams open. ",t);
                             t.Toggle(null);
                         }
                     }
                     if(t.Is(TileType.POISON_BULB)){
                         t.Bump(0);
                     }
                     if(t.Is(FeatureType.WEB)){
                         B.Add("The web is destroyed. ",t);
                         t.RemoveFeature(FeatureType.WEB);
                     }
                     if(t.Is(FeatureType.FORASECT_EGG)){
                         B.Add("The egg is destroyed. ",t);
                         t.RemoveFeature(FeatureType.FORASECT_EGG); //todo: forasect pathing?
                     }
                     if(t.Is(FeatureType.BONES)){
                         B.Add("The bones are scattered. ",t);
                         t.RemoveFeature(FeatureType.BONES);
                     }
                 }
                 else{
                     bool grenade = t.Is(FeatureType.GRENADE);
                     bool barrel = t.Is(TileType.BARREL);
                     bool flaming_barrel = barrel && t.IsBurning();
                     bool torch = t.Is(TileType.STANDING_TORCH);
                     string feature_name = "";
                     int impact_damage_dice = 3;
                     colorchar vis = new colorchar(t.symbol,t.color);
                     switch(t.type){
                     case TileType.CRACKED_WALL:
                         feature_name = "cracked wall";
                         break;
                     case TileType.RUBBLE:
                         feature_name = "pile of rubble";
                         break;
                     case TileType.STATUE:
                         feature_name = "statue";
                         break;
                     }
                     if(grenade){
                         impact_damage_dice = 0;
                         feature_name = "grenade";
                         vis.c = ',';
                         vis.color = Color.Red;
                     }
                     if(flaming_barrel){
                         feature_name = "flaming barrel of oil";
                     }
                     if(barrel){
                         feature_name = "barrel";
                     }
                     if(torch){
                         feature_name = "torch";
                     }
                     if(feature_name == ""){
                         if(wand){
                             if(user == player){
                                 B.Add("The wand grabs at empty space. ",t);
                             }
                             return true;
                         }
                         return false;
                     }
                     string msg = "Throw the " + feature_name + " in which direction? ";
                     bool passable_hack = !t.passable;
                     if(passable_hack){
                         t.passable = true;
                     }
                     List<Tile> line = null;
                     if(user == player){
                         TargetInfo info = t.GetTarget(false,12,0,false,true,false,msg);
                         if(info != null){
                             line = info.extended_line;
                         }
                     }
                     else{
                         line = ai_line;
                     }
                     if(passable_hack){
                         t.passable = false;
                     }
                     if(line != null){
                         if(cast){
                             B.Add(user.You("cast") + " telekinesis. ",user);
                         }
                         if(line.Count == 1){
                             B.Add(user.YouVisible("throw") + " the " + feature_name + " into the ceiling. ",user,t);
                         }
                         else{
                             B.Add(user.YouVisible("throw") + " the " + feature_name + ". ",user,t);
                         }
                         B.DisplayNow();
                         user.attrs[AttrType.SELF_TK_NO_DAMAGE] = 1;
                         switch(t.type){
                         case TileType.CRACKED_WALL:
                         case TileType.RUBBLE:
                         case TileType.STATUE:
                         case TileType.BARREL:
                         case TileType.STANDING_TORCH:
                             if(flaming_barrel){
                                 t.RemoveFeature(FeatureType.FIRE);
                             }
                             t.Toggle(null,TileType.FLOOR);
                             foreach(Tile neighbor in t.TilesAtDistance(1)){
                                 neighbor.solid_rock = false;
                             }
                             break;
                         }
                         if(grenade){
                             t.RemoveFeature(FeatureType.GRENADE);
                             Event e = Q.FindTargetedEvent(t,EventType.GRENADE);
                             if(e != null){
                                 e.dead = true;
                             }
                         }
                         Screen.WriteMapChar(t.row,t.col,M.VisibleColorChar(t.row,t.col));
                         colorchar[,] mem = Screen.GetCurrentMap();
                         int current_row = t.row;
                         int current_col = t.col;
                         //
                         int knockback_strength = 12;
                         if(line.Count == 1){
                             knockback_strength = 0;
                         }
                         int i=0;
                         while(true){
                             Tile t2 = line[i];
                             if(t2 == t){
                                 break;
                             }
                             ++i;
                         }
                         line.RemoveRange(0,i+1);
                         while(knockback_strength > 0){ //if the knockback strength is greater than 1, you're passing *over* at least one tile.
                             Tile t2 = line[0];
                             line.RemoveAt(0);
                             if(!t2.passable){
                                 if(t2.Is(TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR) && impact_damage_dice > 0){
                                     string tilename = t2.TheName(true);
                                     if(t2.type == TileType.HIDDEN_DOOR){
                                         tilename = "a hidden door";
                                         t2.Toggle(null);
                                     }
                                     B.Add("The " + feature_name + " flies into " + tilename + ". ",t2);
                                     t2.Toggle(null);
                                     Screen.WriteMapChar(current_row,current_col,mem[current_row,current_col]);
                                 }
                                 else{
                                     B.Add("The " + feature_name + " flies into " + t2.TheName(true) + ". ",t2);
                                     if(impact_damage_dice > 0){
                                         t2.Bump(M.tile[current_row,current_col].DirectionOf(t2));
                                     }
                                     Screen.WriteMapChar(current_row,current_col,mem[current_row,current_col]);
                                 }
                                 knockback_strength = 0;
                                 break;
                             }
                             else{
                                 if(t2.actor() != null){
                                     B.Add("The " + feature_name + " flies into " + t2.actor().TheName(true) + ". ",t2);
                                     if(t2.actor().type != ActorType.SPORE_POD && !t2.actor().HasAttr(AttrType.SELF_TK_NO_DAMAGE)){
                                         t2.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(impact_damage_dice,6),user,"colliding with a " + feature_name);
                                     }
                                     knockback_strength = 0;
                                     Screen.WriteMapChar(t2.row,t2.col,vis);
                                     Screen.WriteMapChar(current_row,current_col,mem[current_row,current_col]);
                                     current_row = t2.row;
                                     current_col = t2.col;
                                     break;
                                 }
                                 else{
                                     if(t2.Is(FeatureType.WEB)){ //unless perhaps grenades should get stuck and explode in the web?
                                         t2.RemoveFeature(FeatureType.WEB);
                                     }
                                     Screen.WriteMapChar(t2.row,t2.col,vis);
                                     Screen.WriteMapChar(current_row,current_col,mem[current_row,current_col]);
                                     current_row = t2.row;
                                     current_col = t2.col;
                                     Game.GLUpdate();
                                     Thread.Sleep(20);
                                 }
                             }
                             //M.Draw();
                             knockback_strength--;
                         }
                         Tile current = M.tile[current_row,current_col];
                         if(grenade){
                             B.Add("The grenade explodes! ",current);
                             current.ApplyExplosion(1,user,"an exploding grenade");
                         }
                         if(barrel){
                             B.Add("The barrel smashes! ",current);
                             List<Tile> cone = current.TilesWithinDistance(1).Where(x=>x.passable);
                             List<Tile> added = new List<Tile>();
                             foreach(Tile t3 in cone){
                                 foreach(int dir in U.FourDirections){
                                     if(R.CoinFlip() && t3.TileInDirection(dir).passable){
                                         added.AddUnique(t3.TileInDirection(dir));
                                     }
                                 }
                             }
                             cone.AddRange(added);
                             foreach(Tile t3 in cone){
                                 t3.AddFeature(FeatureType.OIL);
                                 if(t3.actor() != null && !t3.actor().HasAttr(AttrType.OIL_COVERED,AttrType.SLIMED)){
                                     if(t3.actor().IsBurning()){
                                         t3.actor().ApplyBurning();
                                     }
                                     else{
                                         t3.actor().attrs[AttrType.OIL_COVERED] = 1;
                                         B.Add(t3.actor().YouAre() + " covered in oil. ",t3.actor());
                                         if(t3.actor() == player){
                                             Help.TutorialTip(TutorialTopic.Oiled);
                                         }
                                     }
                                 }
                             }
                             if(flaming_barrel){
                                 current.ApplyEffect(DamageType.FIRE);
                             }
                         }
                         if(torch){
                             current.AddFeature(FeatureType.FIRE);
                         }
                         user.attrs[AttrType.SELF_TK_NO_DAMAGE] = 0;
                     }
                     else{
                         if(wand){
                             return true;
                         }
                         return false;
                     }
                 }
             }
         }
     }
     else{
         return false;
     }
     return true;
 }
示例#2
0
        public void Toggle(Actor toggler,TileType toggle_to)
        {
            bool lighting_update = false;
            List<PhysicalObject> light_sources = new List<PhysicalObject>();
            TileType original_type = type;
            bool original_passable = passable;
            if(opaque != Prototype(toggle_to).opaque){
                for(int i=row-1;i<=row+1;++i){
                    for(int j=col-1;j<=col+1;++j){
                        if(M.tile[i,j].IsLit(player.row,player.col,true)){
                            lighting_update = true;
                        }
                    }
                }
            }
            if(lighting_update){
                for(int i=row-Global.MAX_LIGHT_RADIUS;i<=row+Global.MAX_LIGHT_RADIUS;++i){
                    for(int j=col-Global.MAX_LIGHT_RADIUS;j<=col+Global.MAX_LIGHT_RADIUS;++j){
                        if(i>0 && i<ROWS-1 && j>0 && j<COLS-1){
                            if(M.actor[i,j] != null && M.actor[i,j].LightRadius() > 0){
                                light_sources.Add(M.actor[i,j]);
                                M.actor[i,j].UpdateRadius(M.actor[i,j].LightRadius(),0);
                            }
                            if(M.tile[i,j].inv != null && M.tile[i,j].inv.light_radius > 0){
                                light_sources.Add(M.tile[i,j].inv);
                                M.tile[i,j].inv.UpdateRadius(M.tile[i,j].inv.light_radius,0);
                            }
                            if(M.tile[i,j].light_radius > 0){
                                light_sources.Add(M.tile[i,j]);
                                M.tile[i,j].UpdateRadius(M.tile[i,j].light_radius,0);
                            }
                            else{
                                if(M.tile[i,j].Is(FeatureType.FIRE)){
                                    light_sources.Add(M.tile[i,j]);
                                    M.tile[i,j].UpdateRadius(1,0);
                                }
                            }
                        }
                    }
                }
            }

            TransformTo(toggle_to);

            if(lighting_update){
                foreach(PhysicalObject o in light_sources){
                    if(o is Actor){
                        Actor a = o as Actor;
                        a.UpdateRadius(0,a.LightRadius());
                    }
                    else{
                        if(o is Tile && o.light_radius == 0 && (o as Tile).Is(FeatureType.FIRE)){
                            o.UpdateRadius(0,1);
                        }
                        else{
                            o.UpdateRadius(0,o.light_radius);
                        }
                    }
                }
            }
            if(Prototype(type).revealed_by_light){
                revealed_by_light = true;
            }
            if(toggler != null && toggler != player){
                if(type == TileType.DOOR_C && original_type == TileType.DOOR_O){
                    if(player.CanSee(this)){
                        B.Add(toggler.TheName(true) + " closes the door. ");
                    }
                }
                if(type == TileType.DOOR_O && original_type == TileType.DOOR_C){
                    if(player.CanSee(this)){
                        B.Add(toggler.TheName(true) + " opens the door. ");
                    }
                }
            }
            if(toggler != null){
                if(original_type == TileType.RUBBLE){
                    B.Add(toggler.YouVisible("scatter") + " the rubble. ",this);
                }
            }
            if(!passable && original_passable){
                if(features.Contains(FeatureType.STABLE_TELEPORTAL)){
                    Event e = Q.FindTargetedEvent(this,EventType.TELEPORTAL);
                    if(e != null){
                        foreach(Tile t in e.area){
                            Event e2 = Q.FindTargetedEvent(t,EventType.TELEPORTAL);
                            if(e2 != null && t.features.Contains(FeatureType.STABLE_TELEPORTAL)){
                                e2.area.Remove(this);
                                if(e2.area.Count == 0){
                                    t.RemoveFeature(FeatureType.STABLE_TELEPORTAL);
                                    t.AddFeature(FeatureType.INACTIVE_TELEPORTAL);
                                    e2.dead = true;
                                }
                            }
                        }
                    }
                }
                foreach(FeatureType ft in new List<FeatureType>(features)){
                    RemoveFeature(ft);
                }
            }
            CheckForSpriteUpdate();
        }