File: ob_methods.c

package info (click to toggle)
crossfire 1.75.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,168 kB
  • sloc: ansic: 83,169; sh: 4,659; perl: 1,736; lex: 1,443; makefile: 1,199; python: 43
file content (146 lines) | stat: -rw-r--r-- 5,034 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Crossfire -- cooperative multi-player graphical RPG and adventure game
 *
 * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
 * Copyright (c) 1992 Frank Tore Johansen
 *
 * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
 * welcome to redistribute it under certain conditions. For details, please
 * see COPYING and LICENSE.
 *
 * The authors can be reached via e-mail at <crossfire@metalforge.org>.
 */

/**
 * @file
 * Those functions deal with the object/type system.
 */

#include <global.h>
#include <ob_methods.h>
#include <ob_types.h>
#include <sproto.h>

/*
 * The following functions are meant for calling methods. No actual behavoir
 * logic should be contained in this code. Code in the common/ directory should
 * be used for logic common to all types, and should always be called by
 * individual method code (i.e. all apply methods should call 'can_apply' from
 * common/). Defaults for all types should not be put here either, as that code
 * belongs in the common/ directory also, referenced to by base_type.
 */

/**
 * Apply an object by running an event hook or an object method. Consider
 * using apply_manual() instead of this function if the applier should check
 * for apply restrictions.
 * @param op The object to apply
 * @param applier The object that executes the apply action
 * @param aflags Special (always apply/unapply) flags
 * @retval 0 A player or monster can't apply objects of that type
 * @retval 1 has been applied, or there was an error applying the object
 * @retval 2 objects of that type can't be applied if not in inventory
 */
method_ret ob_apply(object *op, object *applier, int aflags) {
    method_ret ret;
    ob_methods *methods;

    /* Lauwenmark: Handle for plugin apply event */
    if (execute_event(op, EVENT_APPLY, applier, NULL, NULL, SCRIPT_FIX_ALL) != 0)
        return METHOD_OK;

    for (methods = &type_methods[op->type]; methods; methods = methods->fallback) {
        if (methods->apply) {
            ret = methods->apply(methods, op, applier, aflags);
            if (ret != METHOD_UNHANDLED)
                return ret;
        }
    }
    return METHOD_UNHANDLED;
}

/**
 * Processes an object, giving it the opportunity to move or react.
 * Note: The return value of ob_process doesn't seem to be used anymore.
 * @param op The object to process
 * @retval METHOD_UNHANDLED if the process method does not exist for that objec,
 */
method_ret ob_process(object *op) {
    method_ret ret;
    ob_methods *methods;

    for (methods = &type_methods[op->type]; methods; methods = methods->fallback) {
        if (methods->process) {
            ret = methods->process(methods, op);
            if (ret != METHOD_UNHANDLED)
                return ret;
        }
    }
    return METHOD_UNHANDLED;
}

/**
 * Returns the description of an object, as seen by the given observer.
 * @param op The object to describe
 * @param observer The object to which the description is made
 * @param use_media_tags whether to add media tags or not on the description
 * @param buf Buffer that will contain the description
 * @param size Size of buf
 * @return
 * buf.
 */
char *ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size) {
    ob_methods *methods;

    for (methods = &type_methods[op->type]; methods; methods = methods->fallback) {
        if (methods->describe) {
            methods->describe(methods, op, observer, use_media_tags, buf, size);
            return buf;
        }
    }
    buf[0] = '\0';
    return buf;
}

/**
 * Makes an object move on top of another one.
 * @param op The object over which to move
 * @param victim The object moving over op
 * @param originator The object that is the cause of the move
 * @retval METHOD_UNHANDLED if the process method does not exist for that object
 */
method_ret ob_move_on(object *op, object *victim, object *originator) {
    method_ret ret;
    ob_methods *methods;

    for (methods = &type_methods[op->type]; methods; methods = methods->fallback) {
        if (methods->move_on) {
            ret = methods->move_on(methods, op, victim, originator);
            if (ret != METHOD_UNHANDLED)
                return ret;
        }
    }
    return METHOD_UNHANDLED;
}

/**
 * An object is triggered by another one.
 * @param op The object being triggered
 * @param cause The object that is the cause of the trigger
 * @param state trigger state, 0 for released, other for pushed
 * @retval METHOD_UNHANDLED if the process method does not exist for that object
 * @todo check the exact state values/meaning
 */
method_ret ob_trigger(object *op, object *cause, int state) {
    method_ret ret;
    ob_methods *methods;

    for (methods = &type_methods[op->type]; methods; methods = methods->fallback) {
        if (methods->trigger) {
            ret = methods->trigger(methods, op, cause, state);
            if (ret != METHOD_UNHANDLED)
                return ret;
        }
    }
    return METHOD_UNHANDLED;
}