mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 22:12:59 +00:00 
			
		
		
		
	ru:: hairsnakes implemented
This commit is contained in:
		| @@ -214,7 +214,7 @@ struct entity { | |||||||
|   virtual struct trader* as_trader() { return nullptr; } |   virtual struct trader* as_trader() { return nullptr; } | ||||||
|   virtual struct missile* as_missile() { return nullptr; } |   virtual struct missile* as_missile() { return nullptr; } | ||||||
|  |  | ||||||
|   virtual bool is_disarmer() override { return false; } |   virtual bool is_disarmer() { return false; } | ||||||
|  |  | ||||||
|   int hp; |   int hp; | ||||||
|   int invinc_end; |   int invinc_end; | ||||||
| @@ -260,6 +260,7 @@ struct entity { | |||||||
|   void apply_grav(); |   void apply_grav(); | ||||||
|   void apply_portal_grav(); |   void apply_portal_grav(); | ||||||
|   bool stay_on_screen(); /* returns true if flipped */ |   bool stay_on_screen(); /* returns true if flipped */ | ||||||
|  |   void kill_off_screen(); /* returns true if flipped */ | ||||||
|   virtual void act() { kino(); } |   virtual void act() { kino(); } | ||||||
|   /* for things which can act while not existing */ |   /* for things which can act while not existing */ | ||||||
|   virtual void unact() { } |   virtual void unact() { } | ||||||
| @@ -582,6 +583,17 @@ struct snake : public enemy { | |||||||
|   int max_hp() { return 30; } |   int max_hp() { return 30; } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | struct disnake : public snake { | ||||||
|  |   color_t color() override { return 0x2020F0FF; } | ||||||
|  |   void act() override; | ||||||
|  |   bool is_disarmer() override { return true; } | ||||||
|  |   string get_name() override { return "hairsnake"; } | ||||||
|  |   string get_help() override { return "A magically animated hair."; } | ||||||
|  |   int base_xp() { return 0; } | ||||||
|  |   int max_hp() { return 1; } | ||||||
|  |   virtual void unact() { destroyed = true; } | ||||||
|  |   }; | ||||||
|  |  | ||||||
| struct kestrel : public enemy { | struct kestrel : public enemy { | ||||||
|   xy respawn_vel; |   xy respawn_vel; | ||||||
|   xy siz() override { return {10, 10}; } |   xy siz() override { return {10, 10}; } | ||||||
|   | |||||||
| @@ -105,9 +105,18 @@ void entity::apply_walls() { | |||||||
|     return true; |     return true; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |   auto allside = [this] (int x, int y, eWall b) { | ||||||
|  |     if(b == wRogueWallHidden && is_disarmer()) { | ||||||
|  |       current_room->replace_block_frev(x, y, wRogueWall); | ||||||
|  |       if(current_room->fov[y][x]) | ||||||
|  |         addMessage("Your hairsnake exposes a fake wall!"); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|   for(int x = obb.minx; x < obb.maxx; x++) for(int y = obb.maxy; y < jbb.maxy; y++) { |   for(int x = obb.minx; x < obb.maxx; x++) for(int y = obb.maxy; y < jbb.maxy; y++) { | ||||||
|     eWall b = current_room->at(x, y); |     eWall b = current_room->at(x, y); | ||||||
|     if(walls[b].flags & W_DOWNWARD) continue; |     if(walls[b].flags & W_DOWNWARD) continue; | ||||||
|  |     allside(x, y, b); | ||||||
|     if(walls[b].flags & blocking) { |     if(walls[b].flags & blocking) { | ||||||
|       if(walls[b].flags & W_BOUNCY) { vel.y = -vel.y; apply_grav(); apply_grav(); if(vel.y > 0) vel.y = 0; on_bounce = true; goto again; } |       if(walls[b].flags & W_BOUNCY) { vel.y = -vel.y; apply_grav(); apply_grav(); if(vel.y > 0) vel.y = 0; on_bounce = true; goto again; } | ||||||
|       on_floor = true; |       on_floor = true; | ||||||
| @@ -135,6 +144,7 @@ void entity::apply_walls() { | |||||||
|  |  | ||||||
|   for(int x = obb.minx; x < obb.maxx; x++) for(int y = jbb.miny; y < obb.miny; y++) { |   for(int x = obb.minx; x < obb.maxx; x++) for(int y = jbb.miny; y < obb.miny; y++) { | ||||||
|     eWall b = current_room->at(x, y); |     eWall b = current_room->at(x, y); | ||||||
|  |     allside(x, y, b); | ||||||
|     if(walls[b].flags & W_BLOCK) { |     if(walls[b].flags & W_BLOCK) { | ||||||
|       if(walls[b].flags & W_BOUNCY) { vel.y = -vel.y; apply_grav(); apply_grav(); on_bounce = true; goto again; } |       if(walls[b].flags & W_BOUNCY) { vel.y = -vel.y; apply_grav(); apply_grav(); on_bounce = true; goto again; } | ||||||
|       vel.y /= 2; |       vel.y /= 2; | ||||||
| @@ -158,6 +168,7 @@ void entity::apply_walls() { | |||||||
|  |  | ||||||
|   for(int x = obb.maxx; x < jbb.maxx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { |   for(int x = obb.maxx; x < jbb.maxx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { | ||||||
|     eWall b = current_room->at(x, y); |     eWall b = current_room->at(x, y); | ||||||
|  |     allside(x, y, b); | ||||||
|     if((walls[b].flags & W_DOWNWARD) && b == current_room->at(x-1, y)) continue; |     if((walls[b].flags & W_DOWNWARD) && b == current_room->at(x-1, y)) continue; | ||||||
|     if(walls[b].flags & W_BLOCK) { |     if(walls[b].flags & W_BLOCK) { | ||||||
|       if(walls[b].flags & W_BOUNCY) { vel.x = -vel.x; on_bounce = true; goto again; } |       if(walls[b].flags & W_BOUNCY) { vel.x = -vel.x; on_bounce = true; goto again; } | ||||||
| @@ -175,6 +186,7 @@ void entity::apply_walls() { | |||||||
|    |    | ||||||
|   for(int x = jbb.minx; x < obb.minx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { |   for(int x = jbb.minx; x < obb.minx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { | ||||||
|     eWall b = current_room->at(x, y); |     eWall b = current_room->at(x, y); | ||||||
|  |     allside(x, y, b); | ||||||
|     if((walls[b].flags & W_DOWNWARD) && b == current_room->at(x+1, y)) continue; |     if((walls[b].flags & W_DOWNWARD) && b == current_room->at(x+1, y)) continue; | ||||||
|     if(walls[b].flags & W_BLOCK) { |     if(walls[b].flags & W_BLOCK) { | ||||||
|       if(walls[b].flags & W_BOUNCY) { vel.x = -vel.x; on_bounce = true; goto again; } |       if(walls[b].flags & W_BOUNCY) { vel.x = -vel.x; on_bounce = true; goto again; } | ||||||
| @@ -250,6 +262,13 @@ bool entity::stay_on_screen() { | |||||||
|   return res; |   return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | void entity::kill_off_screen() { | ||||||
|  |   if(where.x < l_margin_at && vel.x < 0) existing = false; | ||||||
|  |   if(where.x > r_margin_at && vel.x > 0) existing = false; | ||||||
|  |   if(where.y < t_margin_at && vel.y < 0) existing = false; | ||||||
|  |   if(where.y > b_margin_at && vel.y > 0) existing = false; | ||||||
|  |   } | ||||||
|  |  | ||||||
| void entity::kino() { | void entity::kino() { | ||||||
|   on_floor = false; |   on_floor = false; | ||||||
|   on_ice = false; |   on_ice = false; | ||||||
| @@ -451,7 +470,7 @@ void snake::act() { | |||||||
|     vel.x = zero_vel.x + dat.d * dat.modv * dir; |     vel.x = zero_vel.x + dat.d * dat.modv * dir; | ||||||
|     dir = -dir; |     dir = -dir; | ||||||
|     } |     } | ||||||
|   if(intersect(get_pixel_bbox(), m.get_pixel_bbox())) { |   if(intersect(get_pixel_bbox(), m.get_pixel_bbox()) && gframeid > invinc_end) { | ||||||
|     if(m.reduce_hp(25)) addMessage("The snake bites you!"); |     if(m.reduce_hp(25)) addMessage("The snake bites you!"); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -690,4 +709,15 @@ cat::cat() { | |||||||
|   col = hrand_elt(cat_colors); |   col = hrand_elt(cat_colors); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | void disnake::act() { | ||||||
|  |   snake::act(); | ||||||
|  |   kill_off_screen(); | ||||||
|  |   for(auto& e: current_room->entities) | ||||||
|  |     if(e->hidden() && e->existing && intersect(e->get_pixel_bbox(), get_pixel_bbox())) { | ||||||
|  |       addMessage("Your hear a sound of a " + e->get_name() + " colliding with a hairsnake."); | ||||||
|  |       e->existing = false; | ||||||
|  |       destroyed = true; | ||||||
|  |       } | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,7 +49,19 @@ randeff trap_detect_cross("Detect cross", "Lets you see traps and secret passage | |||||||
|   m.next.detect_cross = m.current.detect_cross + 0.01 / game_fps * m.current.stats[stat::wis]; |   m.next.detect_cross = m.current.detect_cross + 0.01 / game_fps * m.current.stats[stat::wis]; | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| randeff trap_snake("Snake Hair", "Lets you create snakes that can be used to disarm traps and secret passages.", "You grow snakes on your head!", [] (data &d) { }); | randeff trap_snake("Snake Hair", "Lets you create snakes that can be used to disarm traps and secret passages.", "You grow snakes on your head!", [] (data &d) { | ||||||
|  |   if(d.mode == rev::start || (d.mode == rev::active && d.keystate == 1)) { | ||||||
|  |     auto d = m.get_dat(); | ||||||
|  |     auto mi = std::make_unique<disnake>(); | ||||||
|  |     mi->where = m.where + xy(m.facing * m.get_scale() * m.siz().y * 0.45, 0); | ||||||
|  |     mi->vel = m.vel + xy(m.facing * d.modv * 2, -d.modv * 3.5); | ||||||
|  |     mi->clearg(); | ||||||
|  |     mi->invinc_end = gframeid + 50; | ||||||
|  |     mi->postfix(); | ||||||
|  |     mi->dir = m.facing * 2; | ||||||
|  |     current_room->entities.emplace_back(std::move(mi)); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
| randeff trap_disarm("Disarm traps", "Lets you see all traps on the level for a short time, and to attack them with your [weapon] to destroy them.", "You suddenly feel able to disarm traps with your [weapon]!", [] (data &d) {  | randeff trap_disarm("Disarm traps", "Lets you see all traps on the level for a short time, and to attack them with your [weapon] to destroy them.", "You suddenly feel able to disarm traps with your [weapon]!", [] (data &d) {  | ||||||
|   m.next.rough_detect = 0.1; |   m.next.rough_detect = 0.1; | ||||||
| @@ -158,7 +170,7 @@ void assign_potion_powers() { | |||||||
|   trap_disarm.which_weapon = wpn[1]; |   trap_disarm.which_weapon = wpn[1]; | ||||||
|   using relist = vector<randeff*>; |   using relist = vector<randeff*>; | ||||||
|   find_power("health").randeffs = relist{ pick(&health_heal, &health_regen, &health_protect), random_powers[0] }; |   find_power("health").randeffs = relist{ pick(&health_heal, &health_regen, &health_protect), random_powers[0] }; | ||||||
|   find_power("the thief").randeffs = relist{ pick(&trap_detect, &trap_snake, &trap_disarm), random_powers[1] }; |   find_power("the thief").randeffs = relist{ pick(&trap_detect, &trap_snake, &trap_disarm, &trap_detect_cross), random_powers[1] }; | ||||||
|   find_power("polymorph").randeffs = relist{ pick(&morph_cat, &morph_capy), random_powers[2] }; |   find_power("polymorph").randeffs = relist{ pick(&morph_cat, &morph_capy), random_powers[2] }; | ||||||
|   find_power("reach").randeffs = relist{ pick(&jump_double, &jump_high, &jump_bubble, &jump_light), random_powers[3] }; |   find_power("reach").randeffs = relist{ pick(&jump_double, &jump_high, &jump_bubble, &jump_light), random_powers[3] }; | ||||||
|   find_power("fire").randeffs = relist{ pick(&fire_spit, &fire_weapon), random_powers[4] }; |   find_power("fire").randeffs = relist{ pick(&fire_spit, &fire_weapon), random_powers[4] }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue