--- deliantra/server/common/button.C 2007/06/04 13:04:00 1.35
+++ deliantra/server/common/button.C 2008/04/22 01:06:22 1.45
@@ -1,29 +1,27 @@
/*
- * This file is part of Crossfire TRT, the Multiplayer Online Role Playing Game.
+ * This file is part of Deliantra, the Roguelike Realtime MMORPG.
*
- * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
+ * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
* Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
* Copyright (©) 1992,2007 Frank Tore Johansen
*
- * Crossfire TRT 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 2 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 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.
+ * 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 Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*
- * The authors can be reached via e-mail to
+ * The authors can be reached via e-mail to
*/
#include
-#include
/*
* This code is no longer highly inefficient 8)
@@ -62,6 +60,7 @@
/* if the criteria isn't appropriate, don't do anything */
if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
continue;
+
if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
continue;
@@ -69,6 +68,10 @@
{
case GATE:
case HOLE:
+ if (!tmp->active)
+ tmp->play_sound (tmp->sound
+ ? tmp->sound
+ : sound_find (tmp->type == GATE ? "trigger_gate" : "trigger_hole"));
tmp->value = tmp->stats.maxsp ? !state : state;
tmp->set_speed (0.5);
break;
@@ -81,6 +84,7 @@
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);
if (tmp->stats.food)
tmp->last_eat++;
@@ -88,6 +92,7 @@
break;
case ALTAR:
+ tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_altar"));
tmp->value = 1;
SET_ANIMATION (tmp, tmp->value);
update_object (tmp, UP_OBJ_FACE);
@@ -95,6 +100,7 @@
case BUTTON:
case PEDESTAL:
+ tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_button"));
tmp->value = state;
SET_ANIMATION (tmp, tmp->value);
update_object (tmp, UP_OBJ_FACE);
@@ -105,6 +111,8 @@
break;
case TIMED_GATE:
+ if (!tmp->active)
+ tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_gate"));
tmp->set_speed (tmp->arch->speed);
tmp->value = tmp->arch->value;
tmp->stats.sp = 1;
@@ -143,6 +151,7 @@
break;
case TRIGGER_MARKER:
+ //tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_marker"));
move_marker (tmp);
break;
@@ -208,13 +217,11 @@
void
update_button (object *op)
{
- object *ab, *tmp, *head;
- int tot, any_down = 0, old_value = op->value;
+ int any_down = 0, old_value = op->value;
oblinkpt *obp = 0;
objectlink *ol;
obp = get_button_links (op);
- /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
if (obp)
for (ol = obp->link; ol; ol = ol->next)
{
@@ -224,51 +231,51 @@
continue;
}
- tmp = ol->ob;
+ object *tmp = ol->ob;
+
if (tmp->type == BUTTON)
{
- for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
- /* Bug? The pedestal code below looks for the head of
- * the object, this bit doesn't. I'd think we should check
- * for head here also. Maybe it also makese sense to
- * make the for ab=tmp->above loop common, and alter
- * behaviour based on object within that loop?
- */
+ sint32 total = 0;
+ for (object *ab = tmp->above; ab; ab = ab->above)
/* Basically, if the move_type matches that on what the
- * button wants, we count it. The second check is so that
- * objects don't move (swords, etc) will count. Note that
+ * button wants, we count it. The second check is so that
+ * objects who don't move (swords, etc) will count. Note that
* this means that more work is needed to make buttons
* that are only triggered by flying objects.
*/
if ((ab->move_type & tmp->move_on) || ab->move_type == 0)
- tot += ab->weight * (ab->nrof ? ab->nrof : 1) + ab->carrying;
+ total += ab->head_ ()->total_weight ();
+
+ tmp->value = total >= tmp->weight;
- tmp->value = (tot >= tmp->weight) ? 1 : 0;
- if (tmp->value)
- any_down = 1;
+ any_down = any_down || tmp->value;
}
else if (tmp->type == PEDESTAL)
{
tmp->value = 0;
- for (ab = tmp->above; ab != NULL; ab = ab->above)
+
+ for (object *ab = tmp->above; ab; ab = ab->above)
{
- head = ab->head_ ();
+ object *head = ab->head_ ();
+
/* Same note regarding move_type for buttons above apply here. */
- if (((head->move_type & tmp->move_on) || ab->move_type == 0) &&
- (head->race == tmp->slaying ||
- ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying)) ||
- (!strcmp (tmp->slaying, "player") && head->type == PLAYER)))
+ 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 (tmp->value)
- any_down = 1;
+ any_down = any_down || tmp->value;
}
}
+
if (any_down) /* If any other buttons were down, force this to remain down */
op->value = 1;
+ //LOG(llevDebug, "update_button: %s (%d, %d=%d)\n", &op->name, op->count, op->value, old_value);
+
/* If this button hasn't changed, don't do anything */
if (op->value != old_value)
{
@@ -316,17 +323,20 @@
int
check_altar_sacrifice (const object *altar, const object *sacrifice)
{
- if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) && sacrifice->type != PLAYER)
- {
+ if (!QUERY_FLAG (sacrifice, FLAG_ALIVE)
+ && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED)
+ && sacrifice->type != PLAYER)
+ {
+ if (ARCH_SACRIFICE (altar) == shstr_money
+ && sacrifice->type == MONEY
+ && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
+ return 1;
+
if ((ARCH_SACRIFICE (altar) == sacrifice->arch->archname
|| ARCH_SACRIFICE (altar) == sacrifice->name
|| ARCH_SACRIFICE (altar) == sacrifice->slaying
- || (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
- && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
- return 1;
-
- if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
- && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
+ || strstr (query_base_name (sacrifice, 0), ARCH_SACRIFICE (altar)))
+ && NROF_SACRIFICE (altar) <= sacrifice->number_of ())
return 1;
}
@@ -360,7 +370,7 @@
/* check_altar_sacrifice should have already verified that enough money
* has been dropped.
*/
- if (!strcmp (ARCH_SACRIFICE (altar), "money"))
+ if (ARCH_SACRIFICE (altar) == shstr_money)
{
int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
@@ -368,10 +378,12 @@
if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
number++;
- *sacrifice = decrease_ob_nr (*sacrifice, number);
+ if (!(*sacrifice)->decrease (number))
+ *sacrifice = 0;
}
else
- *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
+ if (!(*sacrifice)->decrease (NROF_SACRIFICE (altar)))
+ *sacrifice = 0;
if (altar->msg)
new_info_map (NDI_BLACK, altar->map, altar->msg);
@@ -418,158 +430,160 @@
switch (op->type)
{
- case TRIGGER_BUTTON:
- if (op->weight > 0)
- {
- if (cause)
- {
- for (tmp = op->above; tmp; tmp = tmp->above)
- /* Comment reproduced from update_buttons(): */
- /* Basically, if the move_type matches that on what the
- * button wants, we count it. The second check is so that
- * objects that don't move (swords, etc) will count. Note that
- * this means that more work is needed to make buttons
- * that are only triggered by flying objects.
- */
+ case TRIGGER_BUTTON:
+ if (op->weight > 0)
+ {
+ if (cause)
+ {
+ for (tmp = op->above; tmp; tmp = tmp->above)
+ /* Comment reproduced from update_buttons(): */
+ /* Basically, if the move_type matches that on what the
+ * button wants, we count it. The second check is so that
+ * objects that don't move (swords, etc) will count. Note that
+ * this means that more work is needed to make buttons
+ * that are only triggered by flying objects.
+ */
+ if ((tmp->move_type & op->move_on) || tmp->move_type == 0)
+ tot += tmp->head_ ()->total_weight ();
+
+ if (tot >= op->weight)
+ push = 1;
+
+ if (op->stats.ac == push)
+ return 0;
+
+ op->stats.ac = push;
+ if (NUM_ANIMATIONS (op) > 1)
+ {
+ SET_ANIMATION (op, push);
+ update_object (op, UP_OBJ_FACE);
+ }
- if ((tmp->move_type & op->move_on) || tmp->move_type == 0)
- {
- tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) + tmp->carrying;
- }
- if (tot >= op->weight)
+ if (in_movement || !push)
+ return 0;
+ }
+ trigger_move (op, push);
+ }
+
+ return 0;
+
+ case TRIGGER_PEDESTAL:
+ if (cause)
+ {
+ for (tmp = op->above; tmp; tmp = tmp->above)
+ {
+ object *head = tmp->head_ ();
+
+ /* See comment in TRIGGER_BUTTON about move_types */
+ if (((head->move_type & op->move_on) || head->move_type == 0)
+ && (head->race == op->slaying || (!strcmp (op->slaying, "player") && head->type == PLAYER)))
+ {
push = 1;
- if (op->stats.ac == push)
- return 0;
- op->stats.ac = push;
- if (NUM_ANIMATIONS (op) > 1)
- {
- SET_ANIMATION (op, push);
- update_object (op, UP_OBJ_FACE);
- }
- if (in_movement || !push)
- return 0;
- }
- trigger_move (op, push);
- }
- return 0;
-
- case TRIGGER_PEDESTAL:
- if (cause)
- {
- for (tmp = op->above; tmp; tmp = tmp->above)
- {
- object *head = tmp->head_ ();
-
- /* See comment in TRIGGER_BUTTON about move_types */
- if (((head->move_type & op->move_on) || head->move_type == 0)
- && (head->race == op->slaying || (!strcmp (op->slaying, "player") && head->type == PLAYER)))
- {
- push = 1;
- break;
- }
- }
-
- if (op->stats.ac == push)
- return 0;
-
- op->stats.ac = push;
-
- if (NUM_ANIMATIONS (op) > 1)
- {
- SET_ANIMATION (op, push);
- update_object (op, UP_OBJ_FACE);
- }
-
- update_object (op, UP_OBJ_FACE);
-
- if (in_movement || !push)
- return 0;
- }
-
- trigger_move (op, push);
- return 0;
-
- case TRIGGER_ALTAR:
- if (cause)
- {
- if (in_movement)
- return 0;
-
- if (operate_altar (op, &cause))
- {
- if (NUM_ANIMATIONS (op) > 1)
- {
- SET_ANIMATION (op, 1);
- update_object (op, UP_OBJ_FACE);
- }
-
- if (op->last_sp >= 0)
- {
- trigger_move (op, 1);
- if (op->last_sp > 0)
- op->last_sp = -op->last_sp;
- }
- else
- {
- /* for trigger altar with last_sp, the ON/OFF
- * status (-> +/- value) is "simulated":
- */
- op->value = !op->value;
- trigger_move (op, 1);
+ break;
+ }
+ }
+
+ if (op->stats.ac == push)
+ return 0;
+
+ op->stats.ac = push;
+
+ if (NUM_ANIMATIONS (op) > 1)
+ {
+ SET_ANIMATION (op, push);
+ update_object (op, UP_OBJ_FACE);
+ }
+
+ update_object (op, UP_OBJ_FACE);
+
+ if (in_movement || !push)
+ return 0;
+ }
+
+ trigger_move (op, push);
+ return 0;
+
+ case TRIGGER_ALTAR:
+ if (cause)
+ {
+ if (in_movement)
+ return 0;
+
+ if (operate_altar (op, &cause))
+ {
+ if (NUM_ANIMATIONS (op) > 1)
+ {
+ SET_ANIMATION (op, 1);
+ update_object (op, UP_OBJ_FACE);
+ }
+
+ if (op->last_sp >= 0)
+ {
+ trigger_move (op, 1);
+ if (op->last_sp > 0)
op->last_sp = -op->last_sp;
- op->value = !op->value;
- }
+ }
+ else
+ {
+ /* for trigger altar with last_sp, the ON/OFF
+ * status (-> +/- value) is "simulated":
+ */
+ op->value = !op->value;
+ trigger_move (op, 1);
+ op->last_sp = -op->last_sp;
+ op->value = !op->value;
+ }
- return cause == NULL;
- }
- else
- return 0;
- }
- else
- {
- if (NUM_ANIMATIONS (op) > 1)
- {
- SET_ANIMATION (op, 0);
- update_object (op, UP_OBJ_FACE);
- }
-
- /* If trigger_altar has "last_sp > 0" set on the map,
- * it will push the connected value only once per sacrifice.
- * Otherwise (default), the connected value will be
- * pushed twice: First by sacrifice, second by reset! -AV
- */
- if (!op->last_sp)
- trigger_move (op, 0);
- else
- {
- op->stats.wc = 0;
- op->value = !op->value;
- op->set_speed (0);
- }
- }
- return 0;
-
- case TRIGGER:
- if (cause)
- {
- if (in_movement)
- return 0;
-
- push = 1;
- }
-
- if (NUM_ANIMATIONS (op) > 1)
- {
- SET_ANIMATION (op, push);
- update_object (op, UP_OBJ_FACE);
- }
-
- trigger_move (op, push);
- return 1;
-
- default:
- LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
- return 0;
+ return cause == NULL;
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ if (NUM_ANIMATIONS (op) > 1)
+ {
+ SET_ANIMATION (op, 0);
+ update_object (op, UP_OBJ_FACE);
+ }
+
+ /* If trigger_altar has "last_sp > 0" set on the map,
+ * it will push the connected value only once per sacrifice.
+ * Otherwise (default), the connected value will be
+ * pushed twice: First by sacrifice, second by reset! -AV
+ */
+ if (!op->last_sp)
+ trigger_move (op, 0);
+ else
+ {
+ op->stats.wc = 0;
+ op->value = !op->value;
+ op->set_speed (0);
+ }
+ }
+ return 0;
+
+ case TRIGGER:
+ if (cause)
+ {
+ if (in_movement)
+ return 0;
+
+ push = 1;
+ }
+
+ if (NUM_ANIMATIONS (op) > 1)
+ {
+ SET_ANIMATION (op, push);
+ update_object (op, UP_OBJ_FACE);
+ }
+
+ trigger_move (op, push);
+ return 1;
+
+ default:
+ LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
+ return 0;
}
}
@@ -883,7 +897,7 @@
if (match && trig->last_sp) // match == having
{
if (trig->last_heal)
- decrease_ob (match);
+ match->decrease ();
trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left
push_button (trig);