Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lightning can now be fired from traps manually #3211

Merged
merged 15 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/player_instances.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,10 @@ long pinstfe_hand_whip(struct PlayerInfo *player, long *n)
trapst = &game.conf.trapdoor_conf.trap_cfgstats[thing->model];
if ((trapst->slappable == 1) && trap_is_active(thing))
{
external_activate_trap_shot_at_angle(thing, player->acamera->orient_a, thing_get(player->hand_thing_idx));
struct TrapStats* trapstat = &game.conf.trap_stats[thing->model];
shotst = get_shot_model_stats(trapstat->created_itm_model);
struct Thing* trgtng = ((shotst->model_flags & ShMF_Boulder) != 0) ? INVALID_THING : get_nearest_enemy_creature_in_sight_and_range_of_trap(thing);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you hardcoded it on the shot model, that is not so very nice. Would this not be a lot better to link to TriggerType 1?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I'm reading it I think it's coded with the Boulder property, not the shot model, isn't?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I'm reading it I think it's coded with the Boulder property, not the shot model, isn't?

Yes, it's the Boulder model flag, not the model itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, indeed better. But still begs the question what we want for the other 90-degree triggered traps, of which by default there are none,...

Would be nice I think if at least it looks in the correct general direction you slap in for the 90-degree angles, or do you disagree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've no idea how that can be done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I will test it like this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdamPlenty I pushed a commit putting all the power in the hands of the mapmaker. How is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdamPlenty I pushed a commit putting all the power in the hands of the mapmaker. How is that?

It doesn't work :(. I cannot slap traps whose Slappable is set to 2.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does

external_activate_trap_shot_at_angle(thing, player->acamera->orient_a, trgtng);
}
break;
case TCls_Object:
Expand Down
119 changes: 104 additions & 15 deletions src/thing_traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ unsigned long remove_traps_around_subtile(MapSubtlCoord stl_x, MapSubtlCoord stl
return total;
}

void external_activate_trap_shot_at_angle(struct Thing *thing, long a2, struct Thing *hand)
void external_activate_trap_shot_at_angle(struct Thing *thing, short angle, struct Thing *trgtng)
{
struct TrapStats* trapstat = &game.conf.trap_stats[thing->model];
if (trapstat->created_itm_model <= 0) {
Expand All @@ -1022,7 +1022,7 @@ void external_activate_trap_shot_at_angle(struct Thing *thing, long a2, struct T
if ((trapstat->activation_type != TrpAcT_CreatureShot)
&& (trapstat->activation_type != TrpAcT_HeadforTarget90))
{
activate_trap(thing, hand);
activate_trap(thing, trgtng);
process_trap_charge(thing);
if (thing->trap.num_shots != INFINITE_CHARGES)
{
Expand All @@ -1035,20 +1035,14 @@ void external_activate_trap_shot_at_angle(struct Thing *thing, long a2, struct T
}
return;
}
struct Thing* shotng = create_shot(&thing->mappos, trapstat->created_itm_model, thing->owner);
if (thing_is_invalid(shotng)) {
return;
if (!thing_is_invalid(trgtng))
{
thing_fire_shot(thing, trgtng, trapstat->created_itm_model, 1, trapstat->hit_type);
}
else
{
trap_fire_shot_without_target(thing, trapstat->created_itm_model, 1, angle);
}
struct ShotConfigStats* shotst = get_shot_model_stats(shotng->model);
shotng->move_angle_xy = a2;
shotng->move_angle_z = 0;
struct ComponentVector cvect;
angles_to_vector(shotng->move_angle_xy, 0, shotst->speed, &cvect);
shotng->veloc_push_add.x.val += cvect.x;
shotng->veloc_push_add.y.val += cvect.y;
shotng->veloc_push_add.z.val += cvect.z;
shotng->state_flags |= TF1_PushAdd;
shotng->shot.hit_type = trapstat->hit_type;
const struct ManfctrConfig* mconf = &game.conf.traps_config[thing->model];
thing->trap.rearm_turn = game.play_gameturn + mconf->shots_delay;
if (thing->trap.num_shots != INFINITE_CHARGES)
Expand Down Expand Up @@ -1129,6 +1123,101 @@ TbBool can_place_trap_on(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoo
return false;
}

void trap_fire_shot_without_target(struct Thing *firing, ThingModel shot_model, char shot_lvl, short angle_xy)
{
struct Thing* shotng;
struct ComponentVector cvect;
struct ShotConfigStats* shotst = get_shot_model_stats(shot_model);
struct TrapStats* trapstat = &game.conf.trap_stats[firing->model];
switch (shotst->fire_logic)
{
case ShFL_Beam:
{
struct Coord3d pos2;
long damage;
// Prepare source position
struct Coord3d pos1;
pos1.x.val = firing->mappos.x.val;
pos1.y.val = firing->mappos.y.val;
pos1.z.val = firing->mappos.z.val;
if (shotst->fire_logic == ShFL_Volley)
{
if (!firing->trap.volley_fire)
{
firing->trap.volley_fire = true;
firing->trap.volley_repeat = shotst->effect_amount - 1; // N x shots + (N - 1) x pauses and one shot is this one
firing->trap.volley_delay = shotst->effect_spacing;
firing->trap.firing_at = 0;
}
else
{
firing->trap.volley_delay = shotst->effect_spacing;
if (firing->trap.volley_repeat == 0)
return;
firing->trap.volley_repeat--;
}
}
firing->move_angle_xy = angle_xy; //visually rotates the trap
pos1.x.val += distance_with_angle_to_coord_x(trapstat->shot_shift_x, firing->move_angle_xy + LbFPMath_PI / 2);
pos1.y.val += distance_with_angle_to_coord_y(trapstat->shot_shift_x, firing->move_angle_xy + LbFPMath_PI / 2);
pos1.x.val += distance_with_angle_to_coord_x(trapstat->shot_shift_y, firing->move_angle_xy);
pos1.y.val += distance_with_angle_to_coord_y(trapstat->shot_shift_y, firing->move_angle_xy);
pos1.z.val += trapstat->shot_shift_z;
// Compute launch angles
pos2.x.val = 0;
pos2.y.val = 0;
pos2.z.val = 0;
if (((shotst->model_flags & ShMF_StrengthBased) != 0) && ((shotst->model_flags & ShMF_ReboundImmune) != 0))
{
pos1.z.val = pos2.z.val;
}
// Compute shot damage
if (shotst->fixed_damage == 0)
{
if ((shotst->model_flags & ShMF_StrengthBased) != 0)
{
damage = calculate_melee_damage(firing);
}
else
{
damage = calculate_shot_damage(firing, shot_model);
}
}
else
{
damage = shotst->damage;
}
if (get_2d_distance(&firing->mappos, &pos2) > shotst->max_range)
{
project_point_to_wall_on_angle(&pos1, &pos2, firing->move_angle_xy, firing->move_angle_z, COORD_PER_STL, shotst->max_range/COORD_PER_STL);
}
shotng = create_shot(&pos2, shot_model, firing->owner);
if (thing_is_invalid(shotng))
return;
draw_lightning(&pos1, &pos2, shotst->effect_spacing, shotst->effect_id);
shotng->health = shotst->health;
shotng->shot.damage = damage;
shotng->parent_idx = firing->index;
break;
}
default:
shotng = create_shot(&firing->mappos, shot_model, firing->owner);
if (thing_is_invalid(shotng)) {
return;
}
shotst = get_shot_model_stats(shotng->model);
shotng->move_angle_xy = angle_xy;
shotng->move_angle_z = 0;
angles_to_vector(shotng->move_angle_xy, 0, shotst->speed, &cvect);
shotng->veloc_push_add.x.val += cvect.x;
shotng->veloc_push_add.y.val += cvect.y;
shotng->veloc_push_add.z.val += cvect.z;
shotng->state_flags |= TF1_PushAdd;
shotng->shot.hit_type = trapstat->hit_type;
break;
}
}

/******************************************************************************/
#ifdef __cplusplus
}
Expand Down
3 changes: 2 additions & 1 deletion src/thing_traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ unsigned long remove_trap(struct Thing *traptng, long *sell_value);
unsigned long remove_trap_on_subtile(MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *sell_value);
unsigned long remove_traps_around_subtile(MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *sell_value);

void external_activate_trap_shot_at_angle(struct Thing *thing, long a2, struct Thing *hand);
void external_activate_trap_shot_at_angle(struct Thing *thing, short angle, struct Thing *trgtng);
void trap_fire_shot_without_target(struct Thing *firing, ThingModel shot_model, char shot_lvl, short angle_xy);

/******************************************************************************/
#ifdef __cplusplus
Expand Down