blob: f0260cf5ecbfd61175ee3645b8cdaa9d517ac36c [file] [log] [blame]
// MorgenGrauen MUDlib
//
// /std/npc/items.c -- Item-Verwaltung fuer NPCs
//
// $Id: items.c 8146 2012-10-30 18:18:14Z Zesstra $
//
// (c) by Padreic (Padreic@mg.mud.de)
#pragma strong_types
#pragma save_types
#pragma range_check
#pragma no_clone
#pragma pedantic
#define NEED_PROTOTYPES
#include <thing/properties.h>
#include <thing/description.h>
#include <living/combat.h>
#undef NEED_PROTOTYPES
#include <npc.h>
#include <properties.h>
#include <combat.h>
#include <config.h>
#include <moving.h>
#include <sys_debug.h>
protected void create()
{
// dieses flag ist nur bis zum ersten move gesetzt. Nimmt danach also auch
Set(NPC_NEEDS_ITEM_INIT, 1); // keinen Speicher mehr in Anspruch.
// Set(P_ITEMS, ({})); // keine initialisierung spart Speicher
}
protected void create_super() {
set_next_reset(-1);
}
protected object* maybe_own_stuff() {
object* obs = all_inventory(environment());
object haufen = present("\nhaufen "+name(WEM),environment());
if( objectp(haufen) ) obs += all_inventory(haufen);
object leiche = present("\nleiche "+name(WEM),environment());
if( objectp(leiche) ) obs += all_inventory(leiche);
return obs;
}
// clont alle Objekte die geclont werden muessen...
protected void _clone_items()
{
int i, j, mode, refresh;
object ob, *inv1;
mixed props, *items;
string file, *inv2;
if (!pointerp(items=QueryProp(P_ITEMS))) return;
if (environment()) { // Liste mit filenamen (inv2) erstellen.
inv1 = maybe_own_stuff();
inv2 = map(inv1, #'load_name);
}
else inv2=({}); // inv1 wird gar nicht mehr benoetigt
for (i=sizeof(items)-1; i>=0; i--) {
ob = items[i][RITEM_OBJECT];
file = items[i][RITEM_FILE];
mode = items[i][RITEM_REFRESH];
refresh = mode & 0x0000ffff;
props = items[i][RITEM_PROPS];
if (props && intp(props)) { // unique Gegenstand?
ob=find_object(file);
if (ob) {
// kann ob aufgenommen werden? Wenn das Objekt in inv1 drin ist, ist es
// im Env oder in einer Leiche oder einem Haufen.
if (member(inv1,ob) > -1) {
if (environment()) {
if (environment(ob) == environment())
tell_room(environment(),
capitalize(name(WER))+" hebt "+ob->name(WEN)+" auf.\n");
else
tell_room(environment(),break_string(
capitalize(name(WER))+" nimmt "+ob->name(WEN)+ " aus "
+environment(ob)->name(WEM) + ".",78));
}
ob->remove(); // zerstoeren und neuladen.
if (ob) destruct(ob);
if (catch(ob=load_object(file);publish))
raise_error(sprintf(
"_clone_items(): %O does not exist or is not loadable\n", file));
ob->move(this_object(), M_NOCHECK);
items[i][RITEM_OBJECT]=ob;
}
else switch( refresh ) {
case REFRESH_DESTRUCT:
if (environment(ob)) {
ob=0; // nicht zuecken, tragen, initialisieren...
break;
}
case REFRESH_ALWAYS:
case REFRESH_REMOVE:
ob->remove();
if (ob) destruct(ob);
if (catch(ob=load_object(file);publish))
raise_error(sprintf("_clone_items(): "
"%O does not exist or is not loadable\n", file));
ob->move(this_object(), M_NOCHECK);
items[i][RITEM_OBJECT]=ob;
break;
case REFRESH_NONE:
default: ob=0; // nicht zuecken, tragen, initialisieren...
}
}
else {
if (catch(ob=load_object(file);publish)) raise_error(sprintf(
"_clone_items(): %O does not exist or is not loadable\n", file));
if (objectp(ob)) ob->move(this_object(), M_NOCHECK);
items[i][RITEM_OBJECT]=ob;
}
} // if (props ...) // also nicht unique
else {
switch( refresh ) {
case REFRESH_DESTRUCT: // erfuellt auch REFRESH_REMOVE Bedingung...
if (ob) {
ob=0; // nicht zuecken, tragen, initialisieren...
break;
}
case REFRESH_REMOVE:
if (ob) {
if(present(ob, this_object())) {
ob=0; // nicht zuecken, tragen, initialisieren...
break;
}
else {
if ((member(inv2, file))==-1) {
ob=0;
}
}
}
case REFRESH_NONE: // wird entfernt nach dem ersten clonen!!!
case REFRESH_ALWAYS:
// schauen ob der Gegenstand im environment liegt.
if ((j=member(inv2, file))!=-1) {
ob=inv1[j]; // inv1 kann leer sein, aber dann ist inv2 auch leer
inv1[j]=0; // wichtig falls mehrere gleiche AddItems
inv2[j]=0; // = 0 setzen um Array kopieren zu vermeiden
if (environment()) {
if (environment() == environment(ob))
tell_room(environment(),
capitalize(name(WER))+" hebt "+ob->name(WEN)+" auf.\n");
else
tell_room(environment(),break_string(
capitalize(name(WER))+" nimmt "+ob->name(WEN)+" aus "
+environment(ob)->name(WEM) + ".",78));
}
}
if (ob) {
ob->remove();
if (ob) destruct(ob);
}
if (catch(ob=clone_object(file);publish)) raise_error(sprintf(
"_clone_items(): %O does not exist or is not loadable\n", file));
ob->move(this_object(), M_NOCHECK);
switch( refresh ) {
case REFRESH_NONE:
items[i] = 0; // Speicher freimachen
break;
case REFRESH_ALWAYS:
items[i][RITEM_OBJECT] = 0; // Objekt "vergessen"
break;
default:
items[i][RITEM_OBJECT] = ob;
}
break;
default: ob=0; // nicht zuecken, tragen, initialisieren...
}
} // if (props ...) else
if (ob) {
if (mappingp(props)) walk_mapping(props, symbol_function("SetProp", ob));
// Eigentlich will man hier sowas wie command("zuecke schwert")
// machen, aber das handling der id's kann nicht sicherstellen,
// dass der NPC die richtige Waffe erwischt, deshalb machen wir
// das tragen hier von Hand.
if (mode & CLONE_WEAR) {
if( mode & CLONE_NO_CHECK ) {
object *armours;
ob->DoUnwear(); // evtl. dem Vorgaenger abnehmen.
UseHands(ob, ob->QueryProp(P_NR_HANDS));
armours=QueryProp(P_ARMOURS)+({ ob });
SetProp(P_ARMOURS, armours);
SetProp(P_TOTAL_AC, QueryProp(P_TOTAL_AC)+ob->QueryProp(P_AC));
ob->SetProp(P_WORN, this_object());
} else {
command( "trage \n"+object_name(ob) );
}
}
if (mode & CLONE_WIELD) {
if( mode & CLONE_NO_CHECK ) {
ob->DoUnwield(); // evtl. dem Vorgaenger abnehmen.
UseHands(ob, ob->QueryProp(P_NR_HANDS));
SetProp(P_WEAPON, ob);
SetProp(P_TOTAL_WC, ob->QueryProp(P_WC));
ob->SetProp(P_WIELDED, this_object());
} else {
command( "zuecke \n"+object_name(ob) );
}
}
} // if (ob)
} // for i
items-=({ 0 }); // REFRESH_NONEs von nicht unique Objekten
if (!sizeof(items)) items=0; // Speicher sparen...
SetProp(P_ITEMS, items);
Set(NPC_NEEDS_ITEM_INIT, 0);
}
public varargs object AddItem(mixed filename, int refresh, mixed props)
{
// Aus Array ein Element auswaehlen
if (pointerp(filename))
filename = filename[random(sizeof(filename))];
// Kein String? -> Fehler
if (!stringp(filename)){
raise_error("AddItem: filename or array of filenames expected.\n");
} else {
// Pfad normieren und eventuell vorhandenes ".c" entfernen
filename = MASTER->_get_path(
filename[<2..]==".c"?filename=filename[0..<3]
: filename,"?");
// Property setzen
SetProp(P_ITEMS, (QueryProp(P_ITEMS)||({}))+
({ ({ 0, filename, refresh, props }) }));
if (environment()) _clone_items();
}
return 0;
}
void reset()
// fuer REFRESH_ Objekte...
{
_clone_items();
}