--- deliantra/server/common/object.C 2007/05/28 21:21:40 1.157
+++ deliantra/server/common/object.C 2007/08/22 20:46:46 1.184
@@ -1,23 +1,22 @@
/*
- * This file is part of Crossfire TRT, the Multiplayer Online Role Playing Game.
+ * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
*
* Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
* Copyright (©) 2001,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.
+ * 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 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
*/
@@ -302,14 +301,14 @@
return 0;
}
- //TODO: generate an event or call into perl for additional checks
if (ob1->self || ob2->self)
{
ob1->optimise ();
ob2->optimise ();
if (ob1->self || ob2->self)
- return 0;
+ if (!cfperl_can_merge (ob1, ob2))
+ return 0;
}
/* Everything passes, must be OK. */
@@ -377,7 +376,6 @@
* multi-object 1 which is closest to the second object.
* If it's not a multi-object, it is returned.
*/
-
object *
get_nearest_part (object *op, const object *pl)
{
@@ -432,22 +430,15 @@
/*
* Sets the owner and sets the skill and exp pointers to owner's current
* skill and experience objects.
+ * ACTUALLY NO! investigate! TODO
*/
void
object::set_owner (object *owner)
{
- if (!owner)
- return;
-
- /* next line added to allow objects which own objects */
- /* Add a check for ownercounts in here, as I got into an endless loop
- * with the fireball owning a poison cloud which then owned the
- * fireball. I believe that was caused by one of the objects getting
- * freed and then another object replacing it. Since the ownercounts
- * didn't match, this check is valid and I believe that cause is valid.
- */
- while (owner->owner)
- owner = owner->owner;
+ // allow objects which own objects
+ if (owner)
+ while (owner->owner)
+ owner = owner->owner;
this->owner = owner;
}
@@ -939,18 +930,19 @@
y = 1;
}
- head = 0;
-
if (more)
{
more->destroy ();
more = 0;
}
- // clear those pointers that likely might have circular references to us
- owner = 0;
- enemy = 0;
- attacked_by = 0;
+ head = 0;
+
+ // clear those pointers that likely might cause circular references
+ owner = 0;
+ enemy = 0;
+ attacked_by = 0;
+ current_weapon = 0;
}
void
@@ -962,6 +954,12 @@
if (destroy_inventory)
destroy_inv (false);
+ if (is_head ())
+ if (sound_destroy)
+ play_sound (sound_destroy);
+ else if (flag [FLAG_MONSTER])
+ play_sound (sound_find ("monster_destroy")); // quick hack, too lazy to create a generic mechanism
+
attachable::destroy ();
}
@@ -1085,28 +1083,24 @@
int check_walk_off = !flag [FLAG_NO_APPLY];
+ if (object *pl = ms.player ())
+ {
+ if (pl->container == this)
+ /* If a container that the player is currently using somehow gets
+ * removed (most likely destroyed), update the player view
+ * appropriately.
+ */
+ pl->close_container ();
+
+ pl->contr->ns->floorbox_update ();
+ }
+
for (tmp = ms.bot; tmp; tmp = tmp->above)
{
/* No point updating the players look faces if he is the object
* being removed.
*/
- if (tmp->type == PLAYER && tmp != this)
- {
- /* If a container that the player is currently using somehow gets
- * removed (most likely destroyed), update the player view
- * appropriately.
- */
- if (tmp->container == this)
- {
- flag [FLAG_APPLIED] = 0;
- tmp->container = 0;
- }
-
- if (tmp->contr->ns)
- tmp->contr->ns->floorbox_update ();
- }
-
/* See if object moving off should effect something */
if (check_walk_off
&& ((move_type & tmp->move_off)
@@ -1118,11 +1112,6 @@
LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
}
- /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
- //TODO: why is this horrible hacka fix? get rid of this code=bug! (schmorp)
- if (tmp->above == tmp)
- tmp->above = 0;
-
last = tmp;
}
@@ -1183,7 +1172,7 @@
object *prev = this;
- for (archetype *at = arch->more; at; at = at->more)
+ for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more)
{
object *op = arch_to_object (at);
@@ -1207,8 +1196,8 @@
{
for (object *tmp = op->head_ (); tmp; tmp = tmp->more)
{
- tmp->x = x + tmp->arch->clone.x;
- tmp->y = y + tmp->arch->clone.y;
+ tmp->x = x + tmp->arch->x;
+ tmp->y = y + tmp->arch->y;
}
return insert_ob_in_map (op, m, originator, flag);
@@ -1243,14 +1232,6 @@
op->remove ();
-#if 0
- if (!m->active != !op->active)
- if (m->active)
- op->activate_recursive ();
- else
- op->deactivate_recursive ();
-#endif
-
if (out_of_map (m, op->x, op->y))
{
LOG (llevError, "Trying to insert object outside the map.\n%s\n", op->debug_desc ());
@@ -1382,7 +1363,6 @@
top = last->below;
}
} /* If objects on this space */
-
if (flag & INS_MAP_LOAD)
top = ms.top;
@@ -1427,13 +1407,9 @@
op->map->dirty = true;
- /* If we have a floor, we know the player, if any, will be above
- * it, so save a few ticks and start from there.
- */
if (!(flag & INS_MAP_LOAD))
if (object *pl = ms.player ())
- if (pl->contr->ns)
- pl->contr->ns->floorbox_update ();
+ pl->contr->ns->floorbox_update ();
/* If this object glows, it may affect lighting conditions that are
* visible to others on this map. But update_all_los is really
@@ -1490,7 +1466,7 @@
/* first search for itself and remove any old instances */
for (tmp = op->ms ().bot; tmp; tmp = tmp->above)
- if (!strcmp (tmp->arch->name, arch_string)) /* same archetype */
+ if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */
tmp->destroy ();
tmp1 = arch_to_object (archetype::find (arch_string));
@@ -1681,8 +1657,6 @@
object *
object::insert (object *op)
{
- object *tmp, *otmp;
-
if (!QUERY_FLAG (op, FLAG_REMOVED))
op->remove ();
@@ -1694,9 +1668,10 @@
CLEAR_FLAG (op, FLAG_OBJ_ORIGINAL);
CLEAR_FLAG (op, FLAG_REMOVED);
+
if (op->nrof)
{
- for (tmp = inv; tmp != NULL; tmp = tmp->below)
+ for (object *tmp = inv; tmp; tmp = tmp->below)
if (object::can_merge (tmp, op))
{
/* return the original object and remove inserted object
@@ -1725,19 +1700,19 @@
else
add_weight (this, (op->weight + op->carrying));
- otmp = this->in_player ();
- if (otmp && otmp->contr)
- if (!QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
+ if (object *otmp = this->in_player ())
+ if (otmp->contr && !QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
otmp->update_stats ();
- op->map = 0;
- op->env = this;
+ op->owner = 0; // its his/hers now. period.
+ op->map = 0;
+ op->env = this;
op->above = 0;
op->below = 0;
- op->x = 0, op->y = 0;
+ op->x = op->y = 0;
/* reset the light list and los of the players on the map */
- if ((op->glow_radius != 0) && map)
+ if (op->glow_radius && map)
{
#ifdef DEBUG_LIGHTS
LOG (llevDebug, " insert_ob_in_ob(): got %s to insert in map/op\n", op->name);
@@ -2351,7 +2326,6 @@
*
* Add a check so we can't pick up invisible objects (0.93.8)
*/
-
int
can_pick (const object *who, const object *item)
{
@@ -2497,7 +2471,7 @@
* it, we save the empty value so that when we load,
* we get this value back again.
*/
- if (get_ob_key_link (&op->arch->clone, canonical_key))
+ if (get_ob_key_link (op->arch, canonical_key))
field->value = 0;
else
{
@@ -2576,7 +2550,6 @@
item = item->env;
}
-
const char *
object::flag_desc (char *desc, int len) const
{
@@ -2620,7 +2593,7 @@
title ? (const char *)title : "",
flag_desc (flagdesc, 512), type);
- if (env)
+ if (!this->flag[FLAG_REMOVED] && env)
p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
if (map)
@@ -2648,13 +2621,10 @@
const materialtype_t *
object::dominant_material () const
{
- if (materialtype_t *mat = name_to_material (materialname))
- return mat;
-
- // omfg this is slow, this has to be temporary :)
- shstr unknown ("unknown");
+ if (materialtype_t *mt = name_to_material (materialname))
+ return mt;
- return name_to_material (unknown);
+ return name_to_material (shstr_unknown);
}
void
@@ -2680,6 +2650,7 @@
esrv_update_item (UPD_FLAGS, this, old_container);
new_draw_info_format (NDI_UNIQUE, 0, this, "You close %s.", query_name (old_container));
+ play_sound (sound_find ("chest_close"));
}
if (new_container)
@@ -2705,7 +2676,57 @@
esrv_update_item (UPD_FLAGS, this, new_container);
esrv_send_inventory (this, new_container);
+ play_sound (sound_find ("chest_open"));
}
}
+object *
+object::force_find (const shstr name)
+{
+ /* cycle through his inventory to look for the MARK we want to
+ * place
+ */
+ for (object *tmp = inv; tmp; tmp = tmp->below)
+ if (tmp->type == FORCE && tmp->slaying == name)
+ return splay (tmp);
+
+ return 0;
+}
+
+void
+object::force_add (const shstr name, int duration)
+{
+ if (object *force = force_find (name))
+ force->destroy ();
+
+ object *force = get_archetype (FORCE_NAME);
+
+ force->slaying = name;
+ force->stats.food = 1;
+ force->speed_left = -1.f;
+
+ force->set_speed (duration ? 1.f / duration : 0.f);
+ force->flag [FLAG_IS_USED_UP] = true;
+ force->flag [FLAG_APPLIED] = true;
+
+ insert (force);
+}
+
+void
+object::play_sound (faceidx sound) const
+{
+ if (!sound)
+ return;
+
+ if (flag [FLAG_REMOVED])
+ return;
+
+ if (env)
+ {
+ if (object *pl = in_player ())
+ pl->contr->play_sound (sound);
+ }
+ else
+ map->play_sound (sound, x, y);
+}