--- deliantra/server/common/button.C 2009/01/08 04:35:03 1.52
+++ deliantra/server/common/button.C 2018/11/17 23:39:59 1.74
@@ -1,23 +1,25 @@
/*
* This file is part of Deliantra, the Roguelike Realtime MMORPG.
- *
- * Copyright (©) 2005,2006,2007,2008 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.
- *
+ *
+ * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
+ * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
+ * Copyright (©) 1992 Frank Tore Johansen
+ *
+ * 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
*/
@@ -35,7 +37,7 @@
* the originator is the player or monster who did something.
*/
static void
-activate_connection_link (objectlink *ol, bool state, object *activator, object *originator)
+activate_connection_link (objectlink *ol, int state, object *activator, object *originator)
{
for (; ol; ol = ol->next)
{
@@ -53,16 +55,16 @@
* re-loaded. As such, just exit this function if that is the case.
*/
- if (QUERY_FLAG (ol->ob, FLAG_FREED))
+ if (ol->ob->flag [FLAG_FREED])
return;
object *tmp = ol->ob;
/* if the criteria isn't appropriate, don't do anything */
- if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
+ if (state && !tmp->flag [FLAG_ACTIVATE_ON_PUSH])
continue;
- if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
+ if (!state && !tmp->flag [FLAG_ACTIVATE_ON_RELEASE])
continue;
switch (tmp->type)
@@ -77,7 +79,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;
@@ -85,8 +87,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++;
}
@@ -133,13 +140,11 @@
case DIRECTOR:
case FIREWALL:
- if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
+ if (!tmp->flag [FLAG_ANIMATE] && tmp->type == FIREWALL)
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;
@@ -201,7 +206,7 @@
*
*/
void
-maptile::trigger (shstr_tmp id, bool state, object *activator, 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;
@@ -234,7 +239,7 @@
if (tmp->type == BUTTON)
{
- sint32 total = 0;
+ weight_t total = 0;
for (object *ab = tmp->above; ab; ab = ab->above)
/* Basically, if the move_type matches that on what the
@@ -252,6 +257,30 @@
}
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)
+ {
+ 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 (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)
@@ -259,11 +288,12 @@
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 (match (tmp->slaying, head, tmp, originator))
+ {
+ tmp->value = 1;
+ break;
+ }
}
any_down = any_down || tmp->value;
@@ -319,13 +349,18 @@
* sacrificed. This fixes a bug of trying to put multiple altars/related
* objects on the same space that take the same sacrifice.
*/
-
int
-check_altar_sacrifice (const object *altar, const object *sacrifice)
+check_altar_sacrifice (object *altar, object *sacrifice, object *originator)
{
- if (!QUERY_FLAG (sacrifice, FLAG_ALIVE)
- && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED)
- && sacrifice->type != PLAYER)
+ if (sacrifice->flag [FLAG_UNPAID]
+ || sacrifice->flag [FLAG_IS_LINKED]
+ || sacrifice->is_player ())
+ return 0;
+
+ if (is_match_expr (ARCH_SACRIFICE (altar)))
+ return match (ARCH_SACRIFICE (altar), sacrifice, altar, originator);
+
+ if (!sacrifice->flag [FLAG_ALIVE])
{
if (ARCH_SACRIFICE (altar) == shstr_money
&& sacrifice->type == MONEY
@@ -353,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)
{
@@ -364,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
@@ -391,7 +426,7 @@
return 1;
}
-void
+static void
trigger_move (object *op, int state, object *originator) /* 1 down and 0 up */
{
op->stats.wc = state;
@@ -423,11 +458,11 @@
* 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;
- int in_movement = op->stats.wc || op->speed;
+ int in_movement = op->stats.wc || op->has_active_speed ();
switch (op->type)
{
@@ -511,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)
{
@@ -529,7 +564,7 @@
else
{
/* for trigger altar with last_sp, the ON/OFF
- * status (-> +/- value) is "simulated":
+ * status (-> +/- value) is "simulated":
*/
op->value = !op->value;
trigger_move (op, 1, cause);
@@ -553,7 +588,7 @@
/* 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
+ * pushed twice: First by sacrifice, second by reset! -AV
*/
if (!op->last_sp)
trigger_move (op, 0, cause);
@@ -706,9 +741,9 @@
return 0;
}
-/* This routine makes monsters who are
+/* This routine makes monsters who are
* standing on the 'mood floor' change their
- * disposition if it is different.
+ * disposition if it is different.
* If floor is to be triggered must have
* a speed of zero (default is 1 for all
* but the charm floor type).
@@ -728,7 +763,7 @@
object *tmp;
for (tmp = ms.top; tmp; tmp = tmp->below)
- if (QUERY_FLAG (tmp, FLAG_MONSTER))
+ if (tmp->flag [FLAG_MONSTER])
break;
/* doesn't effect players, and if there is a player on this space, won't also
@@ -741,10 +776,10 @@
switch (op->last_sp)
{
case 0: /* furious--make all monsters mad */
- if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
- CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
+ if (tmp->flag [FLAG_UNAGGRESSIVE])
+ tmp->clr_flag (FLAG_UNAGGRESSIVE);
- if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
+ if (tmp->flag [FLAG_FRIENDLY])
{
tmp->attack_movement = 0;
/* lots of checks here, but want to make sure we don't
@@ -763,16 +798,16 @@
break;
case 1: /* angry -- get neutral monsters mad */
- if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
- CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
+ if (tmp->flag [FLAG_UNAGGRESSIVE] && !tmp->flag [FLAG_FRIENDLY])
+ tmp->clr_flag (FLAG_UNAGGRESSIVE);
break;
case 2: /* calm -- pacify unfriendly monsters */
- SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
+ tmp->set_flag (FLAG_UNAGGRESSIVE);
break;
case 3: /* make all monsters fall asleep */
- SET_FLAG (tmp, FLAG_SLEEP);
+ tmp->set_flag (FLAG_SLEEP);
break;
case 4: /* charm all monsters */
@@ -782,7 +817,7 @@
if (object *pl = source->ms ().player ())
{
tmp->set_owner (pl);
- SET_FLAG (tmp, FLAG_MONSTER);
+ tmp->set_flag (FLAG_MONSTER);
tmp->stats.exp = 0;
@@ -792,7 +827,7 @@
break;
case 6: // kill monsters
- if (!QUERY_FLAG (tmp, FLAG_FRIENDLY))
+ if (!tmp->flag [FLAG_FRIENDLY])
break;
// FALL THROUGH
@@ -842,13 +877,13 @@
return NULL;
}
-/* check_inv(), a function to search the inventory,
+/* check_inv(), a function to search the inventory,
* of a player and then based on a set of conditions,
- * the square will activate connected items.
+ * the square will activate connected items.
* Monsters can't trigger this square (for now)
- * Values are: last_sp = 1/0 obj/no obj triggers
+ * Values are: last_sp = 1/0 obj/no obj triggers
* last_heal = 1/0 remove/dont remove obj if triggered
- * -b.t. (thomas@nomad.astro.psu.edu
+ * -b.t. (thomas@nomad.astro.psu.edu
*
* Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
* because the check-inventory semantic essentially only applies when
@@ -861,7 +896,7 @@
*
* Wed Jan 10 11:34:26 CET 2007 elmex: fixed this function, we now check
* whether op is on this mapspace or not, because the value (1|0) depends
- * on this information. also make sure to only push_button if op has
+ * on this information. also make sure to only push_button if op has
* a matching item (because when we do a push_button with value=0 timed gates
* will still open)! (i hope i got the semantics right this time)
*