Пример #1
0
void thing_wield_shield (thingp t, tpp shield)
{
    thingp existing_shield = thing_shield_carry_anim(t);

    if (existing_shield) {
        THING_LOG(t, "wield with existing shield %s",
                  thing_logname(existing_shield));
    }

    if (!shield) {
        THING_ERR(t, "could not wield null pointer!");
        return;
    }

    const char *carry_as = tp_shield_carry_anim(shield);

    if (!carry_as) {
        THING_ERR(t, "could not wield shield %s", tp_short_name(shield));
        return;
    }

    tpp what = tp_find(carry_as);
    if (!what) {
        THING_ERR(t, "Could not find %s to wield", carry_as);
        return;
    }

    if (t->shield == shield) {
        if (t->on_server) {
            if (thing_wid(existing_shield)) {
                /*
                 * Add onto existing shield.
                 */
                thing_stats_modify_hp(existing_shield, 
                                      tp_get_stats_max_hp(what));
                return;
            }
        } else {
            return;
        }
    }

    if (thing_is_player(t)) {
        THING_LOG(t, "wield shield %s", tp_short_name(shield));
    }

    t->shield = shield;

    widp shield_carry_anim_wid;

    if (t->on_server) {
        shield_carry_anim_wid = wid_game_map_server_replace_tile(
                                wid_game_map_server_grid_container,
                                t->x,
                                t->y,
                                existing_shield, /* thing */
                                what,
                                0, /* tpp data */
                                0 /* item */,
                                0 /* stats */);
    } else {
        shield_carry_anim_wid = wid_game_map_client_replace_tile(
                                wid_game_map_client_grid_container,
                                t->x, t->y, 0, what);
    }

    if (!shield_carry_anim_wid) {
        THING_ERR(t, "failed wield shield %s", tp_short_name(shield));
        return;
    }

    /*
     * Save the thing id so the client wid can keep track of the shield.
     */
    thingp child = wid_get_thing(shield_carry_anim_wid);
    thing_set_shield_carry_anim(t, child);

    child->dir = t->dir;

    /*
     * Attach to the thing.
     */
    thing_set_owner(child, t);

    if (t->on_server) {
        thing_update(t);
    }
}
Пример #2
0
void thing_dead (levelp level, 
                 thingp t, 
                 thingp killer, 
                 const char *reason, ...)
{
    /*
     * If in a shop, this might be the shopkeeper.
     */
    thingp owner = thing_owner(level, t);

    /*
     * If an arrow, this might be an elf.
     */
    thingp real_killer = 0;

    if (killer) {
        real_killer = thing_owner(level, killer);
        if (!real_killer) {
            real_killer = killer;
        }
    }

    va_list args;

    verify(t);

    tpp tp = thing_tp(t);

    /*
     * If the reason of death was collection, some things we do not want
     * to do.
     */
    if (!t->is_collected) {
        /*
         * When it dies, doth it polymorph and thus avoid the reaper?
         * e.g. a mob spawner dying and creating a smaller one.
         */
        const char *polymorph = tp_polymorph_on_death(tp);

        if (thing_is_sawblade(t) && killer) {
            /*
             * Skip polymorph if there is a killer. We want the blades to
             * just vanish and not get more bloody. That only happens if
             * there is no killer and we force a polymorph.
             */
        } else if (polymorph) {
            tpp what = tp_find(polymorph);
            if (!what) {
                ERR("could now find %s to polymorph into on %s death",
                    polymorph, thing_logname(t));
            }

            /*
             * It doth polymorph.
             */
            t->tp_id = tp_to_id(what);
            t->hp = what->max_hp;
            return;
        }

        /*
         * Or perhaps it does die, but spawns something else, like the
         * player dying and creating a mob spawner.
         */
        const char *spawn = tp_spawn_on_death(tp);
        if (spawn) {
            thingp newt = thing_mob_spawn_on_death(level, t);

            /*
             * If this is the player death then give the gravestone a lot of 
             * health or it can be immediately killed by a lingering explosion 
             * that killed the player too.
             */
            if (newt && thing_is_player(t)) {
                newt->hp = 200;
            }
        }
    }

    /*
     * If a wall is gone, remove the decorations.
     */
    if (thing_is_wall(t)) {
        if (!level->is_being_destroyed) {
            /*
             * Keep walls on edge of level to stop things falling off.
             */
            if ((int)t->x <= 0) {
                return;
            }
            if ((int)t->x >= MAP_WIDTH-1) {
                return;
            }
            if ((int)t->y <= 0) {
                return;
            }
            if ((int)t->y >= MAP_HEIGHT-1) {
                return;
            }

            int dx, dy;
            for (dx = -1; dx <= 1; dx++) {
                for (dy = -1; dy <= 1; dy++) {
                    widp w;
                    while (map_find_wall_deco_at(level, t->x + dx, t->y + dy, &w)) {
                        thing_destroy(level, wid_get_thing(w), __FUNCTION__);
                    }
                }
            }
        }
    }
    /*
     * You only die once.
     */
    if (thing_is_dead(t)) {
        return;
    }

    thing_set_is_dead(t, true);

    /*
     * Bounty for the killer?
     */
    uint32_t xp = tp_get_bonus_score_on_death(tp);
    if (xp && real_killer) {
        /*
         * Did someone throw this weapon and gets the xp?
         */
        int32_t val = tp_get_bonus_score_on_death(tp);

        if (val) {
            real_killer->score += val;

            if (thing_is_player(real_killer)) {
#if 0
                if (thing_is_cloud_effect(killer)) {
                    /*
                        * Too many packets if we kill a lot of things in one
                        * go.
                        *
                        * But it looks nice... 8)
                        */
                } else {
#endif
                    MSG_SHOUT_AT(OVER_THING,
                                 t,
                                 0, 0,
                                 "%%%%font=%s$%%%%fg=%s$+%d XP",
                                 "large", "gold",
                                 val);
#if 0
                }
#endif
            }
        }
    }

    /*
     * Flash briefly red on death.
     */
    if (thing_is_monst(t)        ||
        thing_is_mob_spawner(t)  ||
        thing_is_rock(t)         ||
        thing_is_wall(t)         ||
        thing_is_door(t)) {

        widp w = t->wid;
        if (w) {
            wid_set_mode(w, WID_MODE_ACTIVE);
            if (!wid_is_hidden(w)) {
                wid_set_color(w, WID_COLOR_BLIT, RED);
            }
        }
    }

    /*
     * Boom! If this bomb is not being collected then make it blow up.
     */
    {
#if 0
if (thing_is_treasure(t)) {
CON("%s destroyed",thing_logname(t));
if (owner) {
CON("  %s owner is keeper",thing_logname(owner));
}
if (killer) {
CON("  %s killer ",thing_logname(killer));
}
if (real_killer) {
CON("  %s real_killer ",thing_logname(real_killer));
}
}
#endif
        if (!t->is_collected) {
            if (thing_is_bomb(t)        || 
                thing_is_fireball(t)    ||
                thing_is_bullet(t)) {
                level_place_explosion(level,
                                      0, /* owner */
                                      thing_tp(t),
                                      t->x, t->y,
                                      t->x, t->y);
            }

            /*
             * Breaking stuff in a shop? bad idea.
             */
            if (thing_is_treasure(t)) {
                if (owner && thing_is_shopkeeper(owner)) {
                    if (thing_is_player(real_killer)) {
                        shop_break_message(level, real_killer, owner);
                    } else {
                        shop_whodunnit_break_message(level, real_killer, owner);
                    }
                }
            }
        } else {
            /*
             * Collecting a thing?
             */
            if (thing_is_treasure(t)) {
                if (owner && thing_is_shopkeeper(owner)) {
                    if (thing_is_player(real_killer)) {
                        shop_collect_message(level, real_killer, t);
                    }
                }
            }
        }
    }

    /*
     * Stop bouncing or swaying.
     */
    if (t->wid) {
        if (tp_is_effect_pulse(tp)) {
            wid_scaling_to_pct_in(t->wid, 1.0, 1.0, 0, 0);
        }

        if (tp_is_effect_sway(tp)) {
            wid_rotate_to_pct_in(t->wid, 0, 0, 0, 0);
        }
    }

    /*
     * Log the means of death!
     */
    if (reason) {
        va_start(args, reason);
        thing_dead_(level, t, dynvprintf(reason, args));
        va_end(args);
    } else {
        thing_dead_(level, t, 0);
    }
}