diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 3c21b0b838..bb2082a165 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -1678,6 +1678,18 @@ Cooldown = 0 ; BOUND_CRTRS - allow casting on creatures being affected by Armageddon and Teleport, those who are dragging, leaving or being sacrificed, allowing this may have bad side effects. ; ONLY_DIGGERS - can only be cast on special diggers. ; NO_DIGGERS - can only be cast on creatures that are not special diggers. +; ALL_OBJECTS - can target any object. +; OWNED_OBJECTS +; NEUTRL_OBJECTS +; ENEMY_OBJECTS +; ALL_OBJECTS_PICKUP - can target any object that can be picked up. +; OWNED_OBJECTS_PICKUP +; NEUTRL_OBJECTS_PICKUP +; ENEMY_OBJECTS_PICKUP +; ALL_OBJECTS_SLAP - can target any object that can be slapped. +; OWNED_OBJECTS_SLAP +; NEUTRL_OBJECTS_SLAP +; ENEMY_OBJECTS_SLAP ; Miscellaneous: ; NEEDS_DELAY - Requires a delay defined with 'Cooldown' in game turns before it can be cast again. Castability = @@ -1705,7 +1717,7 @@ SoundSamples = 0 SoundPlayed = 0 Power = 0 0 0 0 0 0 0 0 0 0 Cost = 0 0 0 0 0 0 0 0 0 -Castability = ANYWHERE OWNED_CRTRS CUSTODY_CRTRS ALL_FOOD ALL_GOLD ALL_OBJECTS +Castability = ANYWHERE OWNED_CRTRS CUSTODY_CRTRS ALL_FOOD ALL_GOLD OWNED_OBJECTS_PICKUP Artifact = SPELLBOOK_HOE Properties = INSTINCTIVE PlayerState = PLAYER_STATE_NONE @@ -1768,7 +1780,7 @@ SoundPlayed = 75 Power = 0 0 0 0 0 0 0 0 0 0 Cost = 0 0 0 0 0 0 0 0 0 Duration = 500 -Castability = ALL_GROUND OWNED_CRTRS BOUND_CRTRS CUSTODY_CRTRS OWNED_BOULDERS OWNED_FOOD +Castability = ALL_GROUND OWNED_CRTRS BOUND_CRTRS CUSTODY_CRTRS OWNED_BOULDERS OWNED_FOOD OWNED_OBJECTS_SLAP Artifact = SPELLBOOK_SLAP Properties = INSTINCTIVE PlayerState = PLAYER_STATE_NONE @@ -2280,7 +2292,7 @@ SoundSamples = 0 SoundPlayed = 109 Power = 0 0 0 0 0 0 0 0 0 0 Cost = 0 0 0 0 0 0 0 0 0 -Castability = ANYWHERE OWNED_OBJECTS +Castability = ANYWHERE OWNED_OBJECTS_PICKUP Artifact = NULL Properties = INSTINCTIVE PlayerState = PLAYER_STATE_NONE diff --git a/config/fxdata/objects.cfg b/config/fxdata/objects.cfg index 15312bc50b..3017eec83a 100644 --- a/config/fxdata/objects.cfg +++ b/config/fxdata/objects.cfg @@ -69,7 +69,7 @@ FlameTransparencyFlags = 0 Immobile = 0 ; Initial state, only used for chickens. InitialState = 0 -; Possible properties: EXISTS_ONLY_IN_ROOM, DESTROYED_ON_ROOM_CLAIM, CHOWNED_ON_ROOM_CLAIM, DESTROYED_ON_ROOM_PLACE, BUOYANT, BEATING, HEART, HOLD_IN_HAND, IGNORED_BY_IMPS. +; Possible properties: EXISTS_ONLY_IN_ROOM, DESTROYED_ON_ROOM_CLAIM, CHOWNED_ON_ROOM_CLAIM, DESTROYED_ON_ROOM_PLACE, BUOYANT, BEATING, HEART, HOLD_IN_HAND, IGNORED_BY_IMPS, SLAPPABLE. Properties = ; Function that should be executed to update the object. ; UPDATE_DUNGEON_HEART, UPDATE_CALL_TO_ARMS, UPDATE_ARMOUR, UPDATE_OBJECT_SCALE, UPDATE_POWER_SIGHT, UPDATE_POWER_LIGHTNING, NULL. @@ -325,7 +325,7 @@ Size_Z = 128 MaximumSize = 300 DestroyOnLava = 0 DestroyOnLiquid = 1 -Health = 1000 +Health = 5 FallAcceleration = 9 HandIcon = 59 HandAnimationID = 122 @@ -338,7 +338,7 @@ DrawClass = 2 Persistence = 2 Immobile = 0 InitialState = 1 -Properties = DESTROYED_ON_ROOM_CLAIM +Properties = DESTROYED_ON_ROOM_CLAIM SLAPPABLE UpdateFunction = NULL [object11] diff --git a/src/config_magic.c b/src/config_magic.c index 67f9752b86..7902a67487 100644 --- a/src/config_magic.c +++ b/src/config_magic.c @@ -377,6 +377,14 @@ const struct LongNamedCommand powermodel_castability_commands[] = { {"OWNED_OBJECTS", PwCast_OwnedObjects}, {"NEUTRL_OBJECTS", PwCast_NeutrlObjects}, {"ENEMY_OBJECTS", PwCast_EnemyObjects}, + {"ALL_OBJECTS_PICKUP", PwCast_AllObjectsPickup}, + {"OWNED_OBJECTS_PICKUP", PwCast_OwnedObjectsPickup}, + {"NEUTRL_OBJECTS_PICKUP", PwCast_NeutrlObjectsPickup}, + {"ENEMY_OBJECTS_PICKUP", PwCast_EnemyObjectsPickup}, + {"ALL_OBJECTS_SLAP", PwCast_AllObjectsSlap}, + {"OWNED_OBJECTS_SLAP", PwCast_OwnedObjectsSlap}, + {"NEUTRL_OBJECTS_SLAP", PwCast_NeutrlObjectsSlap}, + {"ENEMY_OBJECTS_SLAP", PwCast_EnemyObjectsSlap}, {NULL, 0}, }; diff --git a/src/config_magic.h b/src/config_magic.h index cd77484343..de43935ce5 100644 --- a/src/config_magic.h +++ b/src/config_magic.h @@ -197,11 +197,19 @@ enum ShotModelFlags { #define PwCast_OwnedObjects (1LL << 32) #define PwCast_NeutrlObjects (1LL << 33) #define PwCast_EnemyObjects (1LL << 34) +#define PwCast_OwnedObjectsPickup (1LL << 35) +#define PwCast_NeutrlObjectsPickup (1LL << 36) +#define PwCast_EnemyObjectsPickup (1LL << 37) +#define PwCast_OwnedObjectsSlap (1LL << 38) +#define PwCast_NeutrlObjectsSlap (1LL << 39) +#define PwCast_EnemyObjectsSlap (1LL << 40) #define PwCast_AllCrtrs (PwCast_CustodyCrtrs|PwCast_OwnedCrtrs|PwCast_AlliedCrtrs|PwCast_EnemyCrtrs|PwCast_NConscCrtrs|PwCast_BoundCrtrs) #define PwCast_AllFood (PwCast_OwnedFood|PwCast_NeutrlFood|PwCast_EnemyFood) #define PwCast_AllGold (PwCast_OwnedGold|PwCast_NeutrlGold|PwCast_EnemyGold) #define PwCast_AllObjects (PwCast_OwnedObjects|PwCast_NeutrlObjects|PwCast_EnemyObjects) +#define PwCast_AllObjectsPickup (PwCast_OwnedObjectsPickup|PwCast_NeutrlObjectsPickup|PwCast_EnemyObjectsPickup) +#define PwCast_AllObjectsSlap (PwCast_OwnedObjectsSlap|PwCast_NeutrlObjectsSlap|PwCast_EnemyObjectsSlap) #define PwCast_AllThings (PwCast_CustodyCrtrs|PwCast_OwnedCrtrs|PwCast_AlliedCrtrs|PwCast_EnemyCrtrs|PwCast_AllFood|PwCast_AllGold|PwCast_OwnedSpell|PwCast_OwnedBoulders|PwCast_AllObjects) #define PwCast_AllGround (PwCast_UnclmdGround|PwCast_NeutrlGround|PwCast_OwnedGround|PwCast_AlliedGround|PwCast_EnemyGround) #define PwCast_NotEnemyGround (PwCast_UnclmdGround|PwCast_NeutrlGround|PwCast_OwnedGround|PwCast_AlliedGround) diff --git a/src/config_objects.c b/src/config_objects.c index ffdaee4eb8..fd0d65701f 100644 --- a/src/config_objects.c +++ b/src/config_objects.c @@ -58,6 +58,7 @@ const struct NamedCommand objects_properties_commands[] = { {"HEART", OMF_Heart }, {"HOLD_IN_HAND", OMF_HoldInHand }, {"IGNORED_BY_IMPS", OMF_IgnoredByImps }, + {"SLAPPABLE", OMF_Slappable }, {NULL, 0}, }; diff --git a/src/config_objects.h b/src/config_objects.h index 99539fb8aa..93577b7fd1 100644 --- a/src/config_objects.h +++ b/src/config_objects.h @@ -58,6 +58,7 @@ enum ObjectModelFlags { OMF_Heart = 0x0040, // Functions as the heart of the dungeon OMF_HoldInHand = 0x0080, // Object can be picked up to hold OMF_IgnoredByImps = 0x0100, // Specialdiggers don't dragging this object + OMF_Slappable = 0x0200, // Object can be slapped }; diff --git a/src/magic_powers.c b/src/magic_powers.c index 757014263d..a0a93361a6 100644 --- a/src/magic_powers.c +++ b/src/magic_powers.c @@ -300,6 +300,24 @@ TbBool can_cast_power_on_thing(PlayerNumber plyr_idx, const struct Thing *thing, } } if ((powerst->can_cast_flags & PwCast_OwnedObjects) != 0) + { + if (thing->owner == plyr_idx) { + return true; + } + } + if ((powerst->can_cast_flags & PwCast_NeutrlObjects) != 0) + { + if (is_neutral_thing(thing)) { + return true; + } + } + if ((powerst->can_cast_flags & PwCast_EnemyObjects) != 0) + { + if ((thing->owner != plyr_idx) && !is_neutral_thing(thing)) { + return true; + } + } + if ((powerst->can_cast_flags & PwCast_OwnedObjectsPickup) != 0) { if (thing->owner == plyr_idx) { if (object_is_pickable_by_hand_to_hold(thing)) { @@ -307,7 +325,7 @@ TbBool can_cast_power_on_thing(PlayerNumber plyr_idx, const struct Thing *thing, } } } - if ((powerst->can_cast_flags & PwCast_NeutrlObjects) != 0) + if ((powerst->can_cast_flags & PwCast_NeutrlObjectsPickup) != 0) { if (is_neutral_thing(thing)) { if (object_is_pickable_by_hand_to_hold(thing)) { @@ -315,7 +333,7 @@ TbBool can_cast_power_on_thing(PlayerNumber plyr_idx, const struct Thing *thing, } } } - if ((powerst->can_cast_flags & PwCast_EnemyObjects) != 0) + if ((powerst->can_cast_flags & PwCast_EnemyObjectsPickup) != 0) { if ((thing->owner != plyr_idx) && !is_neutral_thing(thing)) { if (object_is_pickable_by_hand_to_hold(thing)) { @@ -323,6 +341,30 @@ TbBool can_cast_power_on_thing(PlayerNumber plyr_idx, const struct Thing *thing, } } } + if ((powerst->can_cast_flags & PwCast_OwnedObjectsSlap) != 0) + { + if (thing->owner == plyr_idx) { + if (object_is_slappable(thing)) { + return true; + } + } + } + if ((powerst->can_cast_flags & PwCast_NeutrlObjectsSlap) != 0) + { + if (is_neutral_thing(thing)) { + if (object_is_slappable(thing)) { + return true; + } + } + } + if ((powerst->can_cast_flags & PwCast_EnemyObjectsSlap) != 0) + { + if ((thing->owner != plyr_idx) && !is_neutral_thing(thing)) { + if (object_is_slappable(thing)) { + return true; + } + } + } if ((powerst->can_cast_flags & PwCast_OwnedSpell) != 0) { if (thing->owner == plyr_idx) { @@ -337,7 +379,7 @@ TbBool can_cast_power_on_thing(PlayerNumber plyr_idx, const struct Thing *thing, if ((powerst->can_cast_flags & PwCast_OwnedBoulders) != 0) { if (thing->owner == plyr_idx) { - if (shot_is_slappable(thing, plyr_idx)) { + if (shot_is_slappable_by_player(thing, plyr_idx)) { return true; } } diff --git a/src/packets_input.c b/src/packets_input.c index e9da0d4b77..33614044d3 100644 --- a/src/packets_input.c +++ b/src/packets_input.c @@ -518,7 +518,8 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) { if (player->primary_cursor_state == CSt_PowerHand && (!player->one_click_lock_cursor)) { thing = get_nearest_thing_for_slap(plyr_idx, subtile_coord_center(stl_x), subtile_coord_center(stl_y)); - magic_use_available_power_on_thing(plyr_idx, PwrK_SLAP, 0, stl_x, stl_y, thing, PwMod_Default); + if(!thing_is_invalid(thing)) + magic_use_available_power_on_thing(plyr_idx, PwrK_SLAP, 0, stl_x, stl_y, thing, PwMod_Default); } if ((pckt->control_flags & PCtr_LBtnHeld) == 0) { diff --git a/src/player_instances.c b/src/player_instances.c index d782963ad1..eb27c3922a 100644 --- a/src/player_instances.c +++ b/src/player_instances.c @@ -281,7 +281,7 @@ long pinstfe_hand_whip(struct PlayerInfo *player, int32_t *n) case TCls_Object: { struct Thing* efftng; - if (object_is_slappable(thing, player->id_number)) + if (object_is_slappable_by_player(thing, player->id_number)) { efftng = create_effect(&thing->mappos, TngEff_Dummy, thing->owner); if (!thing_is_invalid(efftng)) diff --git a/src/power_hand.c b/src/power_hand.c index f9cc232406..f36de1f25d 100644 --- a/src/power_hand.c +++ b/src/power_hand.c @@ -278,7 +278,7 @@ TbBool can_thing_be_picked_up2_by_player(const struct Thing *thing, PlayerNumber } } -struct Thing *process_object_being_picked_up(struct Thing *thing, long plyr_idx) +struct Thing *process_object_being_picked_up(struct Thing *thing, PlayerNumber plyr_idx) { struct Thing *picktng = INVALID_THING; struct Coord3d pos; @@ -312,7 +312,7 @@ struct Thing *process_object_being_picked_up(struct Thing *thing, long plyr_idx) { picktng = create_gold_for_hand_grab(thing, plyr_idx); } - else if (object_is_pickable_by_hand_to_hold_by_player(thing, plyr_idx)) + else if (object_is_pickable_by_hand_to_hold(thing)) { picktng = thing; } @@ -720,10 +720,17 @@ void draw_power_hand(void) } } -TbBool object_is_slappable(const struct Thing *thing, long plyr_idx) +TbBool object_is_slappable(const struct Thing* thing) { - if (thing->owner == plyr_idx) { - return (object_is_mature_food(thing)); + struct ObjectConfigStats* objst = get_object_model_stats(thing->model); + return ((objst->model_flags & OMF_Slappable) != 0); +} + +TbBool object_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx) +{ + if (thing->owner == plyr_idx) + { + return object_is_slappable(thing); } return false; } @@ -787,18 +794,18 @@ long near_map_block_thing_filter_ready_for_hand_or_slap(const struct Thing *thin return -1; } -TbBool thing_slappable(const struct Thing *thing, long plyr_idx) +TbBool thing_slappable(const struct Thing *thing, PlayerNumber plyr_idx) { switch (thing->class_id) { case TCls_Object: - return object_is_slappable(thing, plyr_idx); + return object_is_slappable_by_player(thing, plyr_idx); case TCls_Shot: - return shot_is_slappable(thing, plyr_idx); + return shot_is_slappable_by_player(thing, plyr_idx); case TCls_Creature: return creature_is_slappable(thing, plyr_idx); case TCls_Trap: - return trap_is_slappable(thing, plyr_idx); + return trap_is_slappable_by_player(thing, plyr_idx); default: return false; } @@ -1470,8 +1477,7 @@ TbResult use_power_hand(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoor } if (!can_thing_be_picked_up_by_player(thing, plyr_idx)) { - ERRORLOG("The %s owned by player %d is not pickable by player %d",thing_model_name(thing),(int)thing->owner,(int)plyr_idx); - return Lb_OK; + return Lb_FAIL; } if (thing_is_special_box(thing)) { @@ -1524,10 +1530,12 @@ void stop_creatures_around_hand(PlayerNumber plyr_idx, MapSubtlCoord stl_x, Map } } +#define HAND_TO_OBJECT_SLAP_DAMAGE 10 TbBool slap_object(struct Thing *thing) { - if (object_is_mature_food(thing)) { - destroy_object(thing); + if (object_is_slappable(thing)) + { + apply_damage_to_thing(thing, HAND_TO_OBJECT_SLAP_DAMAGE, thing->owner); return true; } return false; diff --git a/src/power_hand.h b/src/power_hand.h index eccda2ca49..9d2086480d 100644 --- a/src/power_hand.h +++ b/src/power_hand.h @@ -44,7 +44,7 @@ TbBool object_is_pickable_by_hand_for_use(const struct Thing *thing, long plyr_i TbBool object_is_pickable_by_hand_to_hold_by_player(const struct Thing* thing, long plyr_idx); TbBool object_is_pickable_by_hand_to_hold(const struct Thing* thing); TbBool thing_is_pickable_by_hand(struct PlayerInfo *player, const struct Thing *thing); -struct Thing *process_object_being_picked_up(struct Thing *thing, long a2); +struct Thing *process_object_being_picked_up(struct Thing *thing, PlayerNumber plyr_idx); void set_power_hand_graphic(unsigned char plyr_idx, long HandAnimationID); TbBool power_hand_is_empty(const struct PlayerInfo *player); TbBool power_hand_is_full(const struct PlayerInfo *player); @@ -68,8 +68,9 @@ TbBool thing_is_picked_up_by_player(const struct Thing *thing, PlayerNumber plyr long get_thing_in_hand_id(const struct Thing* thing, PlayerNumber plyr_idx); TbBool slap_object(struct Thing *thing); -TbBool object_is_slappable(const struct Thing *thing, long plyr_idx); -TbBool thing_slappable(const struct Thing *thing, long plyr_idx); +TbBool object_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx); +TbBool object_is_slappable(const struct Thing* thing); +TbBool thing_slappable(const struct Thing *thing, PlayerNumber plyr_idx); struct Thing *create_power_hand(PlayerNumber owner); void delete_power_hand(PlayerNumber owner); diff --git a/src/thing_objects.c b/src/thing_objects.c index 85e1279081..d5f1632c4f 100644 --- a/src/thing_objects.c +++ b/src/thing_objects.c @@ -1751,7 +1751,6 @@ TngUpdateRet update_object(struct Thing *thing) SYNCDBG(18,"Starting for %s",thing_model_name(thing)); TRACE_THING(thing); - struct ObjectConfigStats* objst = get_object_model_stats(thing->model); if (objst->updatefn_idx > 0) @@ -1785,6 +1784,13 @@ TngUpdateRet update_object(struct Thing *thing) return TUFRet_Deleted; } } + + if (thing->health < 0 && !thing_is_dungeon_heart(thing)) + { + destroy_object(thing); + return TUFRet_Deleted; + } + SYNCDBG(18,"Updating position"); thing->movement_flags &= ~TMvF_IsOnWater; thing->movement_flags &= ~TMvF_IsOnLava; diff --git a/src/thing_shots.c b/src/thing_shots.c index d6a6837677..761fe95b07 100644 --- a/src/thing_shots.c +++ b/src/thing_shots.c @@ -68,7 +68,7 @@ TbBool thing_is_shot(const struct Thing *thing) return true; } -TbBool shot_is_slappable(const struct Thing *thing, PlayerNumber plyr_idx) +TbBool shot_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx) { if (thing->owner == plyr_idx) { diff --git a/src/thing_shots.h b/src/thing_shots.h index e8b988480b..d06b665212 100644 --- a/src/thing_shots.h +++ b/src/thing_shots.h @@ -106,7 +106,7 @@ long get_damage_of_melee_shot(struct Thing *shotng, const struct Thing *target, void create_relevant_effect_for_shot_hitting_thing(struct Thing *shotng, struct Thing *target); int weight_calculated_push_strenght(int weight, int push_strength); -TbBool shot_is_slappable(const struct Thing *thing, PlayerNumber plyr_idx); +TbBool shot_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx); TbBool shot_model_is_navigable(long tngmodel); TbBool shot_model_makes_flesh_explosion(long shot_model); TbBool detonate_shot(struct Thing *shotng, TbBool destroy); diff --git a/src/thing_traps.c b/src/thing_traps.c index e3699eea5f..b419c955c9 100644 --- a/src/thing_traps.c +++ b/src/thing_traps.c @@ -68,7 +68,7 @@ TbBool trap_is_active(const struct Thing *thing) return ((thing->trap.num_shots > 0) && (thing->trap.rearm_turn <= get_gameturn())); } -TbBool trap_is_slappable(const struct Thing *thing, PlayerNumber plyr_idx) +TbBool trap_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx) { struct TrapConfigStats *trapst; if (thing->owner == plyr_idx) diff --git a/src/thing_traps.h b/src/thing_traps.h index 8e04333ed1..c4793df974 100644 --- a/src/thing_traps.h +++ b/src/thing_traps.h @@ -84,7 +84,7 @@ struct Thing* activate_trap_spawn_creature(struct Thing* traptng, unsigned char struct Thing *get_trap_for_position(MapSubtlCoord stl_x, MapSubtlCoord stl_y); struct Thing *get_trap_for_slab_position(MapSlabCoord slb_x, MapSlabCoord slb_y); TbBool trap_is_active(const struct Thing *thing); -TbBool trap_is_slappable(const struct Thing *thing, PlayerNumber plyr_idx); +TbBool trap_is_slappable_by_player(const struct Thing *thing, PlayerNumber plyr_idx); TbBool thing_is_deployed_trap(const struct Thing *thing); short thing_is_destructible_trap(const struct Thing* thing); TbBool thing_is_sellable_trap(const struct Thing* thing);