--- deliantra/server/common/button.C 2009/01/08 03:03:23 1.51 +++ deliantra/server/common/button.C 2009/11/06 13:03:34 1.61 @@ -1,22 +1,23 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team * Copyright (©) 1992,2007 Frank Tore Johansen * - * Deliantra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Deliantra is free software: you can redistribute it and/or modify it under + * the terms of the Affero GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the Affero GNU General Public License + * and the GNU General Public License along with this program. If not, see + * . * * The authors can be reached via e-mail to */ @@ -31,10 +32,11 @@ * elmex: * This function takes a objectlink list with all the objects are going to be activated. * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set. - * The source argument can be 0 or the source object for this activation. + * The activator argument can be 0 or the source object for this activation. + * the originator is the player or monster who did something. */ -void -activate_connection_link (objectlink *ol, bool state, object *source = 0) +static void +activate_connection_link (objectlink *ol, int state, object *activator, object *originator) { for (; ol; ol = ol->next) { @@ -76,7 +78,7 @@ tmp->set_speed (0.5); break; - case CF_HANDLE: + case T_HANDLE: SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state)); update_object (tmp, UP_OBJ_FACE); break; @@ -84,8 +86,13 @@ case SIGN: if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) { - tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_sign")); - new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); + tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("msg_voice")); + + if (originator && originator->contr) + originator->contr->infobox (MSG_CHANNEL ("examine"), format ("T<%s>\n\n%s", &tmp->name, &tmp->msg)); + + new_info_map_except (NDI_UNIQUE | NDI_NAVY, tmp->map, originator, tmp->msg); + if (tmp->stats.food) tmp->last_eat++; } @@ -107,7 +114,7 @@ break; case MOOD_FLOOR: - do_mood_floor (tmp, source); + do_mood_floor (tmp, activator); break; case TIMED_GATE: @@ -136,9 +143,7 @@ move_firewall (tmp); else { - if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ - tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; - + tmp->stats.sp = absdir (tmp->stats.sp + tmp->stats.maxsp); /* next direction */ animate_turning (tmp); } break; @@ -161,7 +166,7 @@ break; case MAPSCRIPT: - cfperl_mapscript_activate (tmp, source, state); + cfperl_mapscript_activate (tmp, state, activator, originator); break; } } @@ -180,14 +185,14 @@ * */ void -push_button (object *op) +push_button (object *op, object *originator) { if (oblinkpt *obp = op->find_link ()) { - if (INVOKE_MAP (TRIGGER, op->map, ARG_STRING (&obp->id), ARG_INT (op->value))) + if (INVOKE_MAP (TRIGGER, op->map, ARG_STRING (&obp->id), ARG_INT (op->value), ARG_OBJECT (op), ARG_OBJECT (originator))) return; - activate_connection_link (obp->link, op->value, op); + activate_connection_link (obp->link, op->value, op, originator); } } @@ -200,13 +205,13 @@ * */ void -maptile::trigger (shstr_tmp id, bool state, object *originator) +maptile::trigger (shstr_tmp id, int state, object *activator, object *originator) { if (INVOKE_MAP (TRIGGER, this, ARG_STRING (&id), ARG_INT (state), ARG_OBJECT (originator))) return; if (oblinkpt *obp = find_link (id)) - activate_connection_link (obp->link, state, originator); + activate_connection_link (obp->link, state, activator, originator); } /* @@ -216,7 +221,7 @@ * button reacts to the (eventual) change of state. */ void -update_button (object *op) +update_button (object *op, object *originator) { int any_down = 0, old_value = op->value; @@ -251,6 +256,7 @@ } else if (tmp->type == PEDESTAL) { + bool is_match = is_match_expr (tmp->slaying); tmp->value = 0; for (object *ab = tmp->above; ab; ab = ab->above) @@ -258,11 +264,35 @@ object *head = ab->head_ (); /* Same note regarding move_type for buttons above apply here. */ - if (((ab->move_type & tmp->move_on) || ab->move_type == 0) - && (head->race == tmp->slaying - || (head->type == SPECIAL_KEY && head->slaying == tmp->slaying) - || (tmp->slaying == shstr_player && head->type == PLAYER))) - tmp->value = 1; + if (((ab->move_type & tmp->move_on) || ab->move_type == 0)) + if (is_match + ? match (tmp->slaying, head, tmp, originator) + : (head->race == tmp->slaying + || (head->type == SPECIAL_KEY && head->slaying == tmp->slaying) + || (tmp->slaying == shstr_player && head->type == PLAYER))) + { + tmp->value = 1; + break; + } + } + + any_down = any_down || tmp->value; + } + else if (tmp->type == T_MATCH) + { + tmp->value = 0; + + for (object *ab = tmp->above; ab; ab = ab->above) + { + object *head = ab->head_ (); + + /* Same note regarding move_type for buttons above apply here. */ + if (((ab->move_type & tmp->move_on) || ab->move_type == 0)) + if (match (tmp->slaying, head, tmp, originator)) + { + tmp->value = 1; + break; + } } any_down = any_down || tmp->value; @@ -279,16 +309,17 @@ { SET_ANIMATION (op, op->value); update_object (op, UP_OBJ_FACE); - push_button (op); /* Make all other buttons the same */ + push_button (op, originator); /* Make all other buttons the same */ } } void -use_trigger (object *op) +use_trigger (object *op, object *originator) { /* Toggle value */ op->value = !op->value; - push_button (op); + + push_button (op, originator); } /* @@ -319,8 +350,14 @@ */ int -check_altar_sacrifice (const object *altar, const object *sacrifice) +check_altar_sacrifice (object *altar, object *sacrifice, object *originator) { + if (sacrifice->flag [FLAG_UNPAID]) + return 0; + + if (is_match_expr (ARCH_SACRIFICE (altar))) + return match (ARCH_SACRIFICE (altar), altar, originator); + if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) && sacrifice->type != PLAYER) @@ -351,7 +388,7 @@ * remaining sacrifice, or is set to NULL if the sacrifice was used up. */ int -operate_altar (object *altar, object **sacrifice) +operate_altar (object *altar, object **sacrifice, object *originator) { if (!altar->map) { @@ -362,7 +399,7 @@ if (!altar->slaying || altar->value) return 0; - if (!check_altar_sacrifice (altar, *sacrifice)) + if (!check_altar_sacrifice (altar, *sacrifice, originator)) return 0; /* check_altar_sacrifice should have already verified that enough money @@ -389,19 +426,20 @@ return 1; } -void -trigger_move (object *op, int state) /* 1 down and 0 up */ +static void +trigger_move (object *op, int state, object *originator) /* 1 down and 0 up */ { op->stats.wc = state; + if (state) { - use_trigger (op); + use_trigger (op, originator); op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.); op->speed_left = -1; } else { - use_trigger (op); + use_trigger (op, originator); op->set_speed (0); } } @@ -420,7 +458,7 @@ * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. */ int -check_trigger (object *op, object *cause) +check_trigger (object *op, object *cause, object *originator) { object *tmp; int push = 0, tot = 0; @@ -460,7 +498,8 @@ if (in_movement || !push) return 0; } - trigger_move (op, push); + + trigger_move (op, push, cause); } return 0; @@ -498,7 +537,7 @@ return 0; } - trigger_move (op, push); + trigger_move (op, push, cause); return 0; case TRIGGER_ALTAR: @@ -507,7 +546,7 @@ if (in_movement) return 0; - if (operate_altar (op, &cause)) + if (operate_altar (op, &cause)) /* TODO: originator? */ { if (NUM_ANIMATIONS (op) > 1) { @@ -517,7 +556,8 @@ if (op->last_sp >= 0) { - trigger_move (op, 1); + trigger_move (op, 1, cause); + if (op->last_sp > 0) op->last_sp = -op->last_sp; } @@ -527,7 +567,7 @@ * status (-> +/- value) is "simulated": */ op->value = !op->value; - trigger_move (op, 1); + trigger_move (op, 1, cause); op->last_sp = -op->last_sp; op->value = !op->value; } @@ -551,7 +591,7 @@ * pushed twice: First by sacrifice, second by reset! -AV */ if (!op->last_sp) - trigger_move (op, 0); + trigger_move (op, 0, cause); else { op->stats.wc = 0; @@ -576,7 +616,7 @@ update_object (op, UP_OBJ_FACE); } - trigger_move (op, push); + trigger_move (op, push, cause); return 1; default: @@ -667,7 +707,7 @@ if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) { - update_button (ol->ob); + update_button (ol->ob, 0); break; } } @@ -882,12 +922,12 @@ match->decrease (); trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left - push_button (trig); + push_button (trig, op); } else if (!match && !trig->last_sp) // match == not having { trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left - push_button (trig); + push_button (trig, op); } }