Parent Directory
|
Revision Log
|
Revision Graph
allow hook_rpg_pc_types to know calling user account
| 1 | <?php |
| 2 | // $Id: rpg.module,v 1.59 2008/04/26 01:03:25 aaron Exp $ |
| 3 | |
| 4 | /** |
| 5 | * @mainpage RPG |
| 6 | * This module provides a full-featured game engine for Drupal. As the name implies, it may be used to create |
| 7 | * an RPG, but may be used for other types of games as well. Various rulesets exist, which may be imported into |
| 8 | * the site to give a base to start from, but a new ruleset may be started from scratch if desired. |
| 9 | */ |
| 10 | |
| 11 | /** |
| 12 | * @file |
| 13 | * This module provides the core engine for RPG. It depends on many include files, so has any functions that may be |
| 14 | * called directly from a menu item, and the basic functions that should be used when directly accessing the system, |
| 15 | * such as rpg_types, rpg_get, rpg_set, etc. |
| 16 | */ |
| 17 | |
| 18 | define('RPG_ACTION_ROUND_DURATION', 1); // default duration of a game turn in real time seconds |
| 19 | define('RPG_ACTION_ROUND_CALENDAR_INCREMENT', 0); // default seconds the default game calendar is incremented in a game turn |
| 20 | define('RPG_MAX_ACTION_POINTS', 120); // default number of action points a character has until they must be recharged |
| 21 | define('RPG_ACTION_RECHARGE_RATE', 720); // default number of rounds that must pass before an action point is restored |
| 22 | |
| 23 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.theme.inc'); |
| 24 | |
| 25 | /** |
| 26 | * implement hook_menu |
| 27 | * |
| 28 | * As this function is rarely called, and is a relatively large function, we've moved this to another file. |
| 29 | * I believe this will be the de facto standard in D6 anyway, makes this an early adopter, I guess.... |
| 30 | * |
| 31 | * @see _rpg_menu_cache() |
| 32 | */ |
| 33 | function rpg_menu($may_cache) { |
| 34 | $items = array(); |
| 35 | |
| 36 | if ($may_cache) { |
| 37 | // include _rpg_menu_cache -- this function defines all the defined menu items |
| 38 | rpg_include_admin(); |
| 39 | $items = _rpg_menu_cache(); |
| 40 | } |
| 41 | else { |
| 42 | // determine things like active char, etc. |
| 43 | // TODO: move this to a better place to always get called once per page load |
| 44 | // i think it's changing in drupal 6 |
| 45 | _rpg_set_globals(); |
| 46 | } |
| 47 | return $items; |
| 48 | } |
| 49 | |
| 50 | /** |
| 51 | * implement hook_perm |
| 52 | * TODO: move this description to an api file |
| 53 | * 'play rpg' => users may play the rpg |
| 54 | * 'create pc rpg object' => users may create a new pc to play in the rpg. this may be limited by certain hooks |
| 55 | * 'administer rpg' => users may administer any aspect of the game, including game settings |
| 56 | * 'create rpg object' => users may create new rpg objects. this may be limited by certain hooks |
| 57 | * 'edit own pc rpg object' => users may edit their own pc object |
| 58 | * 'edit own rpg object' => users may edit their own rpg objects (except the pc object) |
| 59 | * 'edit pc rpg object' => users may edit any pc object |
| 60 | * 'edit rpg object' => users may edit any rpg objects, except other pcs |
| 61 | * 'super in-game rpg' => users have access to special in-game powers, such as teleporting and viewing others' stats, |
| 62 | * but may not necessarily edit overall game settings (which is in the domain of 'administer rpg') |
| 63 | */ |
| 64 | function rpg_perm() { |
| 65 | return array('play rpg', 'view rpg objects', 'create pc rpg object', 'administer rpg', 'create rpg object', 'edit own pc rpg object', 'edit own rpg object', 'edit rpg object', 'super rpg'); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Is the character (as controlled by the user) allowed to view a specific object? In general, this is called by |
| 70 | * rpg/view to determine if an object may be seen. Assuming the user has perms, the character will usually only be |
| 71 | * able to view the object if in the same room as it, or similar circumstances. |
| 72 | * |
| 73 | * calls hook_rpg_view_access, which returns FALSE or TRUE. Any modules that return FALSE will deny access, trumping the others. |
| 74 | */ |
| 75 | function rpg_view_access($who = NULL, $object = NULL) { |
| 76 | if (user_access('administer rpg')) { return TRUE; } |
| 77 | if (!user_access('view rpg objects')) { return FALSE; } |
| 78 | if (is_null($who)) { |
| 79 | global $rpg; |
| 80 | $who = $rpg['pc']; |
| 81 | } |
| 82 | foreach (module_invoke_all('rpg_view_access', $who, $object) as $access) { |
| 83 | if ($access === FALSE) { |
| 84 | return FALSE; |
| 85 | } |
| 86 | } |
| 87 | return TRUE; |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Is the character (as controlled by the user) allowed to edit a specific object? In general, this is called by |
| 92 | * rpg/edit to determine if an object is owned by a user. Assuming the user has perms, the character will usually only be |
| 93 | * able to edit the object if he created it, or similar circumstances. |
| 94 | * |
| 95 | * calls hook_rpg_edit_access, which returns FALSE or TRUE. Any modules that return FALSE will deny access, trumping the others. |
| 96 | */ |
| 97 | function rpg_edit_access($object = NULL) { |
| 98 | if (user_access('administer rpg') || user_access('edit rpg object')) { return TRUE; } |
| 99 | global $user; |
| 100 | $object = rpg_object($object); |
| 101 | if ($object->uid == $user->uid) { |
| 102 | return TRUE; |
| 103 | } |
| 104 | return FALSE; |
| 105 | } |
| 106 | |
| 107 | function rpg_reset_cache() { |
| 108 | db_query("DELETE FROM {cache_rpg}"); |
| 109 | } |
| 110 | |
| 111 | /** |
| 112 | * make sure we save any changes to rpg objects |
| 113 | */ |
| 114 | function rpg_exit() { |
| 115 | _rpg_save_all_marked_objects(); |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * this initializes the global $rpg array and loads some included core rpg files. |
| 120 | * it also sets other rpg global variables, such as active character |
| 121 | * @param $reset |
| 122 | * if set to true, this will reset the global $rpg array (after first saving any changes) |
| 123 | */ |
| 124 | function _rpg_set_globals($reset = false) { |
| 125 | global $rpg, $user; |
| 126 | static $loaded; |
| 127 | |
| 128 | if ($loaded && !$reset) { |
| 129 | return; |
| 130 | } |
| 131 | |
| 132 | // load functions that are used internally, but only when accessing an rpg page |
| 133 | // TODO: remove these and put the calls in proper places |
| 134 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.db.inc'); |
| 135 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.invoke.inc'); |
| 136 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.t.inc'); |
| 137 | |
| 138 | // if we've previously loaded any objects, make sure to save any changes before resetting our global array |
| 139 | if (is_array($rpg)) { |
| 140 | rpg_include_db(); |
| 141 | _rpg_save_all_marked_objects(); |
| 142 | } |
| 143 | |
| 144 | // initialize our global array of rpg objects |
| 145 | $rpg = array(); |
| 146 | |
| 147 | // if we're logged in, get the active pc (if any) |
| 148 | if ($user->uid && user_access('play rpg')) { |
| 149 | $sql = "SELECT rid FROM {rpg_pc} WHERE uid=%d AND active=1"; |
| 150 | $rid = db_result(db_query($sql, $user->uid)); |
| 151 | if ($rid) { |
| 152 | $rpg['pc'] = $rid; |
| 153 | } |
| 154 | } |
| 155 | $loaded = true; |
| 156 | } |
| 157 | |
| 158 | // callback for the game admin page menu item |
| 159 | function rpg_admin_game() { |
| 160 | rpg_include_admin(); |
| 161 | $form = _rpg_admin_game(); |
| 162 | return system_settings_form($form); |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * FAPI definition for the RPG Type admin screen callback. Called with /admin/rpg/types |
| 167 | * |
| 168 | * This is the rpg type admin screen callback. Technically not a form, although it is called as one. This page |
| 169 | * displays a table outlining the various types available, with several actions available for each type from the screen, |
| 170 | * such as edit, delete, attributes, and actions. |
| 171 | * |
| 172 | * @ingroup forms |
| 173 | * @ingroup types |
| 174 | * |
| 175 | * @see theme_rpg_admin_types |
| 176 | */ |
| 177 | function rpg_admin_types() { |
| 178 | $types = rpg_types(NULL, false); |
| 179 | return theme('rpg_admin_types', $types); |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * FAPI definition for the 'Add RPG Type' form. Called with /admin/rpg/types/type/add |
| 184 | * |
| 185 | * This defines the screen used by admins to add a new RPG type. All objects are defined from types, and types may |
| 186 | * inherit from one or more types. Each type will have its own set of attributes and actions, which are also |
| 187 | * inherited, and may be overridden. |
| 188 | * |
| 189 | * @ingroup forms |
| 190 | * @ingroup types |
| 191 | * |
| 192 | * @see _rpg_admin_type_form() |
| 193 | * @see rpg_admin_type_add_validate() |
| 194 | * @see rpg_admin_type_add_submit() |
| 195 | */ |
| 196 | function rpg_admin_type_add() { |
| 197 | rpg_include_admin(); |
| 198 | $type = rpg_new_type(); |
| 199 | $form = _rpg_admin_type_form($type); |
| 200 | $form['new'] = array( |
| 201 | '#type' => 'value', |
| 202 | '#value' => true, |
| 203 | ); |
| 204 | return $form; |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * FAPI definition for the 'Edit RPG Type' form. Called with /admin/rpg/types/type/[TYPE]/edit |
| 209 | * |
| 210 | * This defines the screen used by admins to edit an existing RPG type. All objects are defined from types, and types may |
| 211 | * inherit from one or more types. Each type will have its own set of attributes and actions, which are also |
| 212 | * inherited, and may be overridden. |
| 213 | * |
| 214 | * @param $type |
| 215 | * The string of the type to edit, such as 'tangible' or 'actor'. Called as arg(4) in the url above. |
| 216 | * |
| 217 | * @ingroup forms |
| 218 | * @ingroup types |
| 219 | * |
| 220 | * @see _rpg_admin_type_form() |
| 221 | * @see rpg_admin_type_edit_validate() |
| 222 | * @see rpg_admin_type_edit_submit() |
| 223 | */ |
| 224 | function rpg_admin_type_edit($type) { |
| 225 | rpg_include_admin(); |
| 226 | $type = rpg_types($type, false); |
| 227 | if (!$type['type']) { |
| 228 | drupal_not_found(); |
| 229 | } |
| 230 | $form = _rpg_admin_type_form($type); |
| 231 | return $form; |
| 232 | } |
| 233 | |
| 234 | /** |
| 235 | * Create an empty type array. |
| 236 | * |
| 237 | * Called when adding a new type, whether programatically or from a form. It is not added to the database yet. |
| 238 | * |
| 239 | * @return |
| 240 | * An empty array with key values for each of the expected values. |
| 241 | */ |
| 242 | function rpg_new_type() { |
| 243 | $type = array(); |
| 244 | $type['type'] = ''; |
| 245 | $type['name'] = ''; |
| 246 | $type['parents'] = array(); |
| 247 | $type['shortdesc'] = ''; |
| 248 | $type['longdesc'] = ''; |
| 249 | return $type; |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * validate callback for the 'add type' form |
| 254 | */ |
| 255 | function rpg_admin_type_add_validate($form_id, $form_values) { |
| 256 | $type = rpg_types($form_values['type']); |
| 257 | // if someone's already added the type we're trying to add... |
| 258 | if ($type['type']) { |
| 259 | form_set_error('type', t('The %type type has already been defined. Please choose another machine-readable name.', array('%type' => $type['type']))); |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | /** |
| 264 | * submit callback for the 'add type' form |
| 265 | */ |
| 266 | function rpg_admin_type_add_submit($form_id, $form_values) { |
| 267 | $type['type'] = $form_values['type']; |
| 268 | $type['name'] = $form_values['name']; |
| 269 | $type['parents'] = $form_values['parents']; |
| 270 | $type['shortdesc'] = $form_values['shortdesc']; |
| 271 | $type['longdesc'] = $form_values['longdesc']; |
| 272 | |
| 273 | // rpg_save_type is in an external include file |
| 274 | rpg_include_loadcache(); |
| 275 | // save our new type |
| 276 | rpg_save_type($type); |
| 277 | |
| 278 | drupal_set_message(t('Your changes to the object type have been saved.')); |
| 279 | |
| 280 | return 'admin/rpg/types/type/' . $type['type']; |
| 281 | } |
| 282 | |
| 283 | /** |
| 284 | * validate callback for the 'edit type' form |
| 285 | */ |
| 286 | function rpg_admin_type_edit_validate($form_id, $form_values) { |
| 287 | $type = rpg_types($form_values['type']); |
| 288 | // if type type we're editing has been deleted since we began editing... |
| 289 | if (!$type['type']) { |
| 290 | form_set_error('type', t('There was an error in processing your form; that type is no longer in the database.')); |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | /** |
| 295 | * submit callback for the 'edit type' form |
| 296 | */ |
| 297 | function rpg_admin_type_edit_submit($form_id, $form_values) { |
| 298 | $type = rpg_types($form_values['type']); |
| 299 | |
| 300 | $type['name'] = $form_values['name']; |
| 301 | $type['parents'] = $form_values['parents']; |
| 302 | $type['shortdesc'] = $form_values['shortdesc']; |
| 303 | $type['longdesc'] = $form_values['longdesc']; |
| 304 | |
| 305 | // rpg_save_type is in an external include file |
| 306 | rpg_include_loadcache(); |
| 307 | rpg_save_type($type); |
| 308 | |
| 309 | drupal_set_message(t('Your changes to the object type have been saved.')); |
| 310 | } |
| 311 | |
| 312 | function rpg_admin_type_attributes_form($type) { |
| 313 | $type = rpg_types($type); |
| 314 | if (!$type['type']) { |
| 315 | drupal_not_found(); |
| 316 | } |
| 317 | |
| 318 | drupal_set_title(t('Attributes for @type', array('@type' => $type['name']))); |
| 319 | |
| 320 | // include the include file w/ our helper function |
| 321 | rpg_include_admin(); |
| 322 | |
| 323 | return _rpg_admin_type_attributes_form($type); |
| 324 | } |
| 325 | |
| 326 | /** |
| 327 | * FAPI definition for the 'Add new RPG Attribute' form. Called with /admin/rpg/types/type/[TYPE]/attributes/add/[[ATTRIBUTE]] |
| 328 | * |
| 329 | * This defines the screen used by admins to add an attribute for an existing RPG type. If called with an optional |
| 330 | * $attribute string of an existing attribute defined by a parent of the type, then this screen defines an overridden |
| 331 | * attribute. |
| 332 | * |
| 333 | * @param $type |
| 334 | * The string of the type to edit, such as 'tangible' or 'actor'. Called as arg(4) in the url above. |
| 335 | * @param $attribute |
| 336 | * If given (as the last arg), then it's a string of the attribute to override. Otherwise, it will add a new attribute. |
| 337 | * |
| 338 | * @ingroup forms |
| 339 | * @ingroup attributes |
| 340 | * |
| 341 | * @see _rpg_admin_type_attribute_add() |
| 342 | * @see rpg_admin_type_attribute_add_validate() |
| 343 | * @see rpg_admin_type_attribute_add_submit() |
| 344 | */ |
| 345 | function rpg_admin_type_attribute_add($type, $attribute = NULL) { |
| 346 | $type = rpg_types($type); |
| 347 | if (!$type['type']) { |
| 348 | drupal_not_found(); |
| 349 | } |
| 350 | |
| 351 | // include the include file w/ our helper function |
| 352 | rpg_include_admin(); |
| 353 | |
| 354 | return _rpg_admin_type_attribute_add($type, $attribute); |
| 355 | } |
| 356 | |
| 357 | /** |
| 358 | * FAPI definition for the 'Add new RPG Action' form. Called with /admin/rpg/types/type/[TYPE]/actions/add/[[ACTION]] |
| 359 | * |
| 360 | * This defines the screen used by admins to add an action for an existing RPG type. If called with an optional |
| 361 | * $action string of an existing action defined by a parent of the type, then this screen defines an overridden |
| 362 | * action. |
| 363 | * |
| 364 | * @param $type |
| 365 | * The string of the type to edit, such as 'tangible' or 'actor'. Called as arg(4) in the url above. |
| 366 | * @param $action |
| 367 | * If given (as the last arg), then it's a string of the action to override. Otherwise, it will add a new action. |
| 368 | * |
| 369 | * @ingroup forms |
| 370 | * @ingroup attributes |
| 371 | * |
| 372 | * @see _rpg_admin_type_action_add() |
| 373 | * @see rpg_admin_type_action_add_validate() |
| 374 | * @see rpg_admin_type_action_add_submit() |
| 375 | */ |
| 376 | function rpg_admin_type_action_add($type, $action = NULL) { |
| 377 | $type = rpg_types($type); |
| 378 | if (!$type['type']) { |
| 379 | drupal_not_found(); |
| 380 | } |
| 381 | |
| 382 | // include the include file w/ our helper function |
| 383 | rpg_include_admin(); |
| 384 | |
| 385 | return _rpg_admin_type_action_add($type, $action); |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * FAPI definition for the 'Add new RPG Event' form. Called with /admin/rpg/types/type/[TYPE]/events/add/[[ACTION]] |
| 390 | * |
| 391 | * This defines the screen used by admins to add an event for an existing RPG type. If called with an optional |
| 392 | * $event string of an existing event defined by a parent of the type, then this screen defines an overridden |
| 393 | * event. |
| 394 | * |
| 395 | * @param $type |
| 396 | * The string of the type to edit, such as 'tangible' or 'actor'. Called as arg(4) in the url above. |
| 397 | * @param $event |
| 398 | * If given (as the last arg), then it's a string of the event to override. Otherwise, it will add a new event. |
| 399 | * |
| 400 | * @ingroup forms |
| 401 | * @ingroup attributes |
| 402 | * |
| 403 | * @see _rpg_admin_type_event_add() |
| 404 | * @see rpg_admin_type_event_add_validate() |
| 405 | * @see rpg_admin_type_event_add_submit() |
| 406 | */ |
| 407 | function rpg_admin_type_event_add($type, $event = NULL) { |
| 408 | $type = rpg_types($type); |
| 409 | if (!$type['type']) { |
| 410 | drupal_not_found(); |
| 411 | } |
| 412 | |
| 413 | // include the include file w/ our helper function |
| 414 | rpg_include_admin(); |
| 415 | |
| 416 | return _rpg_admin_type_event_add($type, $event); |
| 417 | } |
| 418 | |
| 419 | function rpg_admin_type_attribute_edit($type, $attribute) { |
| 420 | $type = rpg_types($type); |
| 421 | $attribute = rpg_attributes($attribute); |
| 422 | if (!isset($type['type']) || !isset($attribute['attribute']) || !isset($type['attributes']['defined'][$attribute['attribute']])) { |
| 423 | drupal_not_found(); |
| 424 | } |
| 425 | |
| 426 | drupal_set_title(t('Edit @attribute Attribute', array('@attribute' => $attribute['name']))); |
| 427 | rpg_include_admin(); |
| 428 | return _rpg_admin_attribute_edit_form($type, $type['attributes']['defined'][$attribute['attribute']]); |
| 429 | } |
| 430 | |
| 431 | function rpg_admin_type_action_edit($type, $action) { |
| 432 | $type = rpg_types($type); |
| 433 | $action = rpg_actions($action); |
| 434 | if (!isset($type['type']) || !isset($action['action']) || !isset($type['actions']['defined'][$action['action']])) { |
| 435 | drupal_not_found(); |
| 436 | } |
| 437 | |
| 438 | drupal_set_title(t('Edit @action action', array('@action' => $action['name']))); |
| 439 | rpg_include_admin(); |
| 440 | return _rpg_admin_action_edit_form($type, $type['actions']['defined'][$action['action']]); |
| 441 | } |
| 442 | |
| 443 | function rpg_admin_type_event_edit($type, $event) { |
| 444 | $type = rpg_types($type); |
| 445 | $event = rpg_events($event); |
| 446 | if (!isset($type['type']) || !isset($event['event']) || !isset($type['events']['defined'][$event['event']])) { |
| 447 | drupal_not_found(); |
| 448 | } |
| 449 | |
| 450 | drupal_set_title(t('Edit @event event', array('@event' => $event['name']))); |
| 451 | rpg_include_admin(); |
| 452 | return _rpg_admin_event_edit_form($type, $type['events']['defined'][$event['event']]); |
| 453 | } |
| 454 | |
| 455 | function rpg_admin_type_attribute_add_submit($form_id, $form_values) { |
| 456 | // include rpg_attribute_add |
| 457 | rpg_include_loadcache(); |
| 458 | |
| 459 | $attribute = array(); |
| 460 | $attribute['attribute'] = $form_values['attribute']; |
| 461 | $attribute['name'] = $form_values['name']; |
| 462 | $attribute['class'] = $form_values['class']; |
| 463 | $attribute['get'] = $form_values['get']; |
| 464 | $attribute['verify'] = $form_values['verify']; |
| 465 | $attribute['set'] = $form_values['set']; |
| 466 | $attribute['default_value'] = $form_values['default_value']; |
| 467 | $attribute['form_display'] = $form_values['form_display']; |
| 468 | |
| 469 | $attribute = rpg_attribute_add($form_values['type'], $attribute); |
| 470 | // $attribute = rpg_attribute_add($form_values['type'], $form_values['class'], $form_values['attribute'], $form_values['name']); |
| 471 | |
| 472 | if (isset($attribute)) { |
| 473 | drupal_set_message(t("The attribute '@attribute' has been added.", array('@attribute' => $form_values['name']))); |
| 474 | return 'admin/rpg/types/type/' . $form_values['type'] . '/attributes/edit/' . $attribute['attribute']; |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | function rpg_admin_type_attribute_edit_submit($form_id, $form_values) { |
| 479 | // include rpg_attribute_edit |
| 480 | rpg_include_loadcache(); |
| 481 | |
| 482 | $attribute = array(); |
| 483 | $attribute['attribute'] = $form_values['attribute']; |
| 484 | $attribute['name'] = $form_values['name']; |
| 485 | $attribute['class'] = $form_values['class']; |
| 486 | $attribute['description'] = $form_values['description']; |
| 487 | $attribute['get'] = $form_values['get']; |
| 488 | $attribute['verify'] = $form_values['verify']; |
| 489 | $attribute['set'] = $form_values['set']; |
| 490 | $attribute['default_value'] = $form_values['default_value']; |
| 491 | $attribute['form_display'] = $form_values['form_display']; |
| 492 | |
| 493 | $class = rpg_attribute_classes($attribute['class']); |
| 494 | |
| 495 | $settings = module_invoke($class['module'], 'rpg_attribute_class_settings', 'save', $class['class']); |
| 496 | |
| 497 | foreach ((array)($settings) as $key => $setting) { |
| 498 | $attribute[$setting] = $form_values[$setting]; |
| 499 | } |
| 500 | |
| 501 | $attribute = _rpg_attribute_edit($form_values['type'], $attribute); |
| 502 | |
| 503 | drupal_set_message(t('Your changes have been recorded.')); |
| 504 | return 'admin/rpg/types/type/' . $form_values['type'] . '/attributes/edit/' . $attribute['attribute']; |
| 505 | } |
| 506 | |
| 507 | function rpg_admin_type_action_add_submit($form_id, $form_values) { |
| 508 | // include _rpg_action_add |
| 509 | rpg_include_loadcache(); |
| 510 | |
| 511 | $action = array(); |
| 512 | $action['action'] = $form_values['action']; |
| 513 | $action['name'] = $form_values['name']; |
| 514 | |
| 515 | $action = _rpg_action_add($form_values['type'], $action); //$form_values['action'], $form_values['name']); |
| 516 | |
| 517 | drupal_set_message(t("The action '@action' has been added.", array('@action' => $form_values['name']))); |
| 518 | return 'admin/rpg/types/type/' . $form_values['type'] . '/actions/edit/' . $action['action']; |
| 519 | } |
| 520 | |
| 521 | /** |
| 522 | * This is when you submit the action edit admin screen. makes any changes to that action, which will |
| 523 | * be inherited by inherited types. |
| 524 | */ |
| 525 | function rpg_admin_type_action_edit_submit($form_id, $form_values) { |
| 526 | // include rpg_action_edit |
| 527 | rpg_include_loadcache(); |
| 528 | $type = rpg_types($form_values['type']); |
| 529 | |
| 530 | $action = array( |
| 531 | 'action' => $form_values['action'], |
| 532 | 'name' => $form_values['name'], |
| 533 | 'type' => $type['type'], |
| 534 | 'description' => $form_values['description'], |
| 535 | 'php' => $form_values['php'], |
| 536 | 'expose' => $form_values['expose'], |
| 537 | ); |
| 538 | |
| 539 | $action = _rpg_action_edit($type['type'], $action); |
| 540 | |
| 541 | drupal_set_message(t('Your changes have been recorded.')); |
| 542 | return 'admin/rpg/types/type/' . $form_values['type'] . '/actions/edit/' . $action['action']; |
| 543 | } |
| 544 | |
| 545 | function rpg_admin_type_event_add_submit($form_id, $form_values) { |
| 546 | // include _rpg_event_add |
| 547 | rpg_include_loadcache(); |
| 548 | |
| 549 | $event = array(); |
| 550 | $event['event'] = $form_values['event']; |
| 551 | $event['name'] = $form_values['name']; |
| 552 | |
| 553 | $event = _rpg_event_add($form_values['type'], $event); //$form_values['event'], $form_values['name']); |
| 554 | |
| 555 | drupal_set_message(t("The event '@event' has been added.", array('@event' => $form_values['name']))); |
| 556 | return 'admin/rpg/types/type/' . $form_values['type'] . '/events/edit/' . $event['event']; |
| 557 | } |
| 558 | |
| 559 | /** |
| 560 | * This is when you submit the event edit admin screen. makes any changes to that event, which will |
| 561 | * be inherited by inherited types. |
| 562 | */ |
| 563 | function rpg_admin_type_event_edit_submit($form_id, $form_values) { |
| 564 | // include rpg_event_edit |
| 565 | rpg_include_loadcache(); |
| 566 | $type = rpg_types($form_values['type']); |
| 567 | |
| 568 | $event = array( |
| 569 | 'event' => $form_values['event'], |
| 570 | 'name' => $form_values['name'], |
| 571 | 'type' => $type['type'], |
| 572 | 'description' => $form_values['description'], |
| 573 | 'php' => $form_values['php'], |
| 574 | 'expose' => $form_values['expose'], |
| 575 | ); |
| 576 | |
| 577 | $event = _rpg_event_edit($type['type'], $event); |
| 578 | |
| 579 | drupal_set_message(t('Your changes have been recorded.')); |
| 580 | return 'admin/rpg/types/type/' . $form_values['type'] . '/events/edit/' . $event['event']; |
| 581 | } |
| 582 | |
| 583 | /** |
| 584 | * This loads all defined attributes into the system. |
| 585 | * @param $attribute |
| 586 | * If given, then return an array defining that attribute (by machine-readable name). |
| 587 | * Otherwise, return an array of all attributes. |
| 588 | * @param $cached |
| 589 | * If false, then force the cache to be reloaded. Otherwise, simply return the attribute(s) |
| 590 | * from the cache. |
| 591 | */ |
| 592 | function rpg_attributes($attribute = NULL, $cached = true) { |
| 593 | static $attributes; |
| 594 | if (!isset($attributes) || !$cached) { |
| 595 | if ($cached && $cache = cache_get('rpg_attributes', 'cache_rpg')) { |
| 596 | $attributes = unserialize($cache->data); |
| 597 | } |
| 598 | else { |
| 599 | // define _rpg_load_attributes(); |
| 600 | rpg_include_loadcache(); |
| 601 | $attributes = _rpg_load_attributes(); |
| 602 | cache_set('rpg_attributes', 'cache_rpg', serialize($attributes)); |
| 603 | } |
| 604 | } |
| 605 | if (isset($attribute)) { |
| 606 | return $attributes[$attribute]; |
| 607 | } |
| 608 | return $attributes; |
| 609 | } |
| 610 | |
| 611 | /** |
| 612 | * This loads all defined actions into the system. |
| 613 | * @param $action |
| 614 | * If given, then return an array defining that action (by machine-readable name). |
| 615 | * Otherwise, return an array of all actions. |
| 616 | * @param $cached |
| 617 | * If false, then force the cache to be reloaded. Otherwise, simply return the action(s) |
| 618 | * from the cache. |
| 619 | */ |
| 620 | function rpg_actions($action = NULL, $cached = true) { |
| 621 | static $actions; |
| 622 | if (!isset($actions) || !$cached) { |
| 623 | if ($cached && $cache = cache_get('rpg_actions', 'cache_rpg')) { |
| 624 | $actions = unserialize($cache->data); |
| 625 | } |
| 626 | else { |
| 627 | // define _rpg_load_actions(); |
| 628 | rpg_include_loadcache(); |
| 629 | $actions = _rpg_load_actions(); |
| 630 | cache_set('rpg_actions', 'cache_rpg', serialize($actions)); |
| 631 | } |
| 632 | } |
| 633 | if (isset($action)) { |
| 634 | return $actions[$action]; |
| 635 | } |
| 636 | return $actions; |
| 637 | } |
| 638 | |
| 639 | /** |
| 640 | * This loads all defined events into the system. |
| 641 | * @param $event |
| 642 | * If given, then return an array defining that event (by machine-readable name). |
| 643 | * Otherwise, return an array of all events. |
| 644 | * @param $cached |
| 645 | * If false, then force the cache to be reloaded. Otherwise, simply return the event(s) |
| 646 | * from the cache. |
| 647 | */ |
| 648 | function rpg_events($event = NULL, $cached = true) { |
| 649 | static $events; |
| 650 | if (!isset($events) || !$cached) { |
| 651 | if ($cached && $cache = cache_get('rpg_events', 'cache_rpg')) { |
| 652 | $events = unserialize($cache->data); |
| 653 | } |
| 654 | else { |
| 655 | // define _rpg_load_events(); |
| 656 | rpg_include_loadcache(); |
| 657 | $events = _rpg_load_events(); |
| 658 | cache_set('rpg_events', 'cache_rpg', serialize($events)); |
| 659 | } |
| 660 | } |
| 661 | if (isset($event)) { |
| 662 | return $events[$event]; |
| 663 | } |
| 664 | return $events; |
| 665 | } |
| 666 | |
| 667 | function rpg_admin_type_actions($type) { |
| 668 | $type = rpg_types($type); |
| 669 | if (!$type['type']) { |
| 670 | drupal_not_found(); |
| 671 | } |
| 672 | |
| 673 | drupal_set_title(t('Actions for @type', array('@type' => $type['name']))); |
| 674 | |
| 675 | // include the include file w/ our helper function |
| 676 | rpg_include_admin(); |
| 677 | |
| 678 | return _rpg_admin_type_actions_form($type); |
| 679 | } |
| 680 | |
| 681 | function rpg_admin_type_events($type) { |
| 682 | $type = rpg_types($type); |
| 683 | if (!$type['type']) { |
| 684 | drupal_not_found(); |
| 685 | } |
| 686 | |
| 687 | drupal_set_title(t('Events for @type', array('@type' => $type['name']))); |
| 688 | |
| 689 | // include the include file w/ our helper function |
| 690 | rpg_include_admin(); |
| 691 | |
| 692 | return _rpg_admin_type_events_form($type); |
| 693 | } |
| 694 | |
| 695 | /** |
| 696 | * this is the main function called to play each turn, from the /rpg/play menu item |
| 697 | */ |
| 698 | function rpg_play($object = NULL, $action = NULL, $who = NULL, $target = NULL, $item = NULL) { |
| 699 | global $rpg, $user; |
| 700 | // if we already have a character, process the action. otherwise, show a select screen |
| 701 | if ($rpg['pc']) { |
| 702 | // allow modules to hijack the process, such as during character creation |
| 703 | // in fact, character selection can happen elsewhere as well! |
| 704 | module_invoke_all('rpg_play', $rpg['pc']); |
| 705 | |
| 706 | // if we have an action, such as rpg/play/88/drop/53/88, then process it |
| 707 | // TODO: move this to rpg_action? and add all args to the module_invoke, thus this function will have no args! |
| 708 | if (isset($action)) { |
| 709 | $action = array( |
| 710 | '#object' => $object, |
| 711 | '#action' => $action, |
| 712 | '#who' => $who ? $who : $rpg['pc'], |
| 713 | '#target' => $target, |
| 714 | '#what' => $item, |
| 715 | ); |
| 716 | rpg_action_process($action); |
| 717 | // make sure the pc is able to act (next action round, etc) |
| 718 | /* if (rpg_may_act($pc)) { |
| 719 | // create the event from the action, saving it to check later |
| 720 | $event = rpg_create_event($pc, $action, $target, $what); |
| 721 | |
| 722 | // process our new event |
| 723 | rpg_event_process_threads(1); |
| 724 | |
| 725 | // make sure it's been processed. if not, we'll set a message to that effect |
| 726 | rpg_event_check_if_processed($event); |
| 727 | } |
| 728 | else { |
| 729 | // create a message saying the pc isn't able to act yet |
| 730 | // TODO: seperate from rpg_message.module. maybe make it simply a drupal_set_message? or better yet, a theme function |
| 731 | $message = array( |
| 732 | '#who' => $pc, |
| 733 | '#message' => t('You may not yet act.'), |
| 734 | ); |
| 735 | rpg_message($message); |
| 736 | }*/ |
| 737 | } |
| 738 | // display our game play page |
| 739 | return theme('rpg_play', $rpg['pc']); |
| 740 | } |
| 741 | else { |
| 742 | // we don't have a character yet, so go to the character selection page |
| 743 | drupal_goto('rpg/select'); |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | function rpg_character_select_page() { |
| 748 | global $user; |
| 749 | |
| 750 | // clear any old characters (effective 'logging off' the character) |
| 751 | $sql = "UPDATE {rpg_pc} SET active=0 WHERE uid=%d"; |
| 752 | db_query($sql, $user->uid); |
| 753 | |
| 754 | $pcs = rpg_user_pcs($user); |
| 755 | $selected = arg(2); |
| 756 | |
| 757 | // if we have selected a pc, then set the active pc for that user to it and go to rpg/play |
| 758 | if ($selected && in_array($selected, $pcs)) { |
| 759 | $sql = "UPDATE {rpg_pc} SET active=1 WHERE uid=%d AND rid=%d"; |
| 760 | db_query($sql, $user->uid, $selected); |
| 761 | drupal_goto('rpg/play'); |
| 762 | } |
| 763 | |
| 764 | // print our list of available characters for this user |
| 765 | $output .= theme('rpg_character_select_page', $user, $pcs); |
| 766 | return $output; |
| 767 | } |
| 768 | |
| 769 | /** |
| 770 | * this will return an array of the pc object id's owned by a certain user $account |
| 771 | */ |
| 772 | function rpg_user_pcs($account) { |
| 773 | static $pcs = array(); |
| 774 | if (!isset($pcs[$account->uid])) { |
| 775 | $pcs[$account->uid] = array(); |
| 776 | $sql = "SELECT rid FROM {rpg_pc} WHERE uid=%d"; |
| 777 | $results = db_query($sql, $account->uid); |
| 778 | while ($result = db_fetch_array($results)) { |
| 779 | $pcs[$account->uid][] = $result['rid']; |
| 780 | } |
| 781 | } |
| 782 | return $pcs[$account->uid]; |
| 783 | } |
| 784 | |
| 785 | /** |
| 786 | * callback for rpg/create/[TYPE] |
| 787 | * |
| 788 | * this either displays a list of types, or the form to create an object of the specified type. |
| 789 | */ |
| 790 | function rpg_create_page() { |
| 791 | $type = arg(3); |
| 792 | if (arg(2) == 'pc') { |
| 793 | return rpg_create_pc_page(); |
| 794 | } |
| 795 | if (!$type) { |
| 796 | global $user; |
| 797 | $types = rpg_types(); |
| 798 | $pc_types = rpg_available_pc_types($user); |
| 799 | $admin_access = user_access('rpg admin'); |
| 800 | if (empty($types) && $admin_access) { |
| 801 | $output .= t('There are currently no RPG object types defined. You may define these at the !admin.', array('!admin' => l(t('types admin page'), 'admin/rpg/types'))); |
| 802 | } |
| 803 | foreach ($types as $type) { |
| 804 | $link = ''; |
| 805 | $is_pc_type = isset($pc_types[$type['type']]); |
| 806 | // TODO: this needs to be redone; actor is now in the realm of rulesets |
| 807 | if ($is_pc_type && ($admin_access || (rpg_user_access('create pc', $type) && rpg_may_create_pc($user, $type)))) { |
| 808 | $link = l($type['name'], 'rpg/create/pc/' . $type['type']); |
| 809 | } |
| 810 | else if (!$is_pc_type && ($admin_access || rpg_user_access('create', $type))) { |
| 811 | $link = l($type['name'], 'rpg/create/type/' . $type['type']); |
| 812 | } |
| 813 | if ($link) { |
| 814 | $output .= '<p>' . $link . '<br />' . $type['shortdesc'] . '</p>'; |
| 815 | } |
| 816 | } |
| 817 | |
| 818 | if ($output) { |
| 819 | // TODO: theme this |
| 820 | return $output; |
| 821 | } |
| 822 | else { |
| 823 | drupal_access_denied(); |
| 824 | } |
| 825 | } |
| 826 | else { |
| 827 | return rpg_create_object_page($type, arg(4)); |
| 828 | } |
| 829 | } |
| 830 | |
| 831 | function rpg_edit_page() { |
| 832 | if (arg(2) && is_numeric(arg(2))) { |
| 833 | $object = rpg_object(arg(2)); |
| 834 | if ($object->rid) { |
| 835 | if (!rpg_edit_access($object)) { |
| 836 | drupal_access_denied(); |
| 837 | } |
| 838 | $form = drupal_get_form('rpg_form_object', $object); |
| 839 | return theme('rpg_edit_object_page', $object, $form); |
| 840 | } |
| 841 | } |
| 842 | drupal_not_found(); |
| 843 | } |
| 844 | |
| 845 | function rpg_view_page() { |
| 846 | if (is_numeric(arg(2))) { |
| 847 | $object = arg(2); |
| 848 | global $rpg; |
| 849 | if (!rpg_view_access($rpg['pc'], $object)) { |
| 850 | drupal_access_denied(); |
| 851 | } |
| 852 | if (!rpg_id($object)) { |
| 853 | drupal_not_found(); |
| 854 | } |
| 855 | return theme('rpg_view_object_page', $object); |
| 856 | } |
| 857 | else { |
| 858 | if (!user_access('administer rpg')) { |
| 859 | drupal_access_denied(); |
| 860 | } |
| 861 | $sql = "SELECT rid FROM {rpg} ORDER BY created DESC"; |
| 862 | $limit = variable_get('rpg_browse_object_limit', 20); |
| 863 | $results = pager_query($sql, $limit); |
| 864 | $objects = array(); |
| 865 | while ($rid = db_fetch_array($results)) { |
| 866 | $objects[$rid['rid']] = $rid['rid']; |
| 867 | } |
| 868 | return theme('rpg_browse_page', $objects); |
| 869 | } |
| 870 | drupal_not_found(); |
| 871 | } |
| 872 | |
| 873 | /** |
| 874 | * this displays the form to create an object of $type |
| 875 | * |
| 876 | * @param $type |
| 877 | * This is the string of the object. |
| 878 | * @param $subtype |
| 879 | * This will set the object type as $subtype, assuming $subtype is a child of $type. |
| 880 | */ |
| 881 | function rpg_create_object_page($type, $subtype = NULL) { |
| 882 | global $user; |
| 883 | $type = rpg_types($type); |
| 884 | if ($subtype) { |
| 885 | $subtype = rpg_types($subtype); |
| 886 | if (!rpg_type_is_a($subtype, $type['type'])) { |
| 887 | drupal_not_found(); |
| 888 | } |
| 889 | else { |
| 890 | $type = $subtype; |
| 891 | } |
| 892 | } |
| 893 | if (!user_access('admin rpg') && !rpg_user_access('create', $type)) { |
| 894 | drupal_access_denied(); |
| 895 | } |
| 896 | $object = rpg_new_rpg_object($type, $user); |
| 897 | $form = drupal_get_form('rpg_form_object', $object); |
| 898 | return theme('rpg_create_object_page', $object, $type, $form); |
| 899 | } |
| 900 | |
| 901 | function rpg_available_pc_types($user) { |
| 902 | static $avail; |
| 903 | |
| 904 | if (!isset($avail)) { |
| 905 | $avail = array(); |
| 906 | $pc_types = module_invoke_all('rpg_pc_types', $user); |
| 907 | $types = rpg_types(); |
| 908 | foreach ($pc_types as $type) { |
| 909 | if (isset($types[$type])) { |
| 910 | $avail[$type] = $types[$type]; |
| 911 | } |
| 912 | } |
| 913 | } |
| 914 | return $avail; |
| 915 | } |
| 916 | |
| 917 | function rpg_create_pc_page() { |
| 918 | global $user; |
| 919 | $pc_types = rpg_available_pc_types($user); |
| 920 | $pc_type = arg(3); |
| 921 | if ($pc_type && isset($pc_types[$pc_type])) { |
| 922 | $type = $pc_types[$pc_type]; |
| 923 | } |
| 924 | else if ($pc_type) { |
| 925 | drupal_not_found(); |
| 926 | } |
| 927 | if (isset($type['type'])) { |
| 928 | // we call this, because an admin might set certain user roles to have only a limited number of pc's |
| 929 | // or maybe, for instance, only one of each race or class |
| 930 | if (user_access('admin rpg') || (rpg_user_access('create pc', $type) && rpg_may_create_pc($user, $type))) { |
| 931 | $pc = rpg_new_rpg_object($type, $user); |
| 932 | $form = drupal_get_form('rpg_form_object', $pc); |
| 933 | return theme('rpg_create_pc_page', $pc, $type, $form); |
| 934 | } |
| 935 | else { |
| 936 | drupal_access_denied(); |
| 937 | } |
| 938 | } |
| 939 | $available_types = array(); |
| 940 | foreach($pc_types as $type) { |
| 941 | // we call this, because an admin might set certain user roles to have only a limited number of pc's |
| 942 | // or maybe, for instance, only one of each race or class |
| 943 | if (rpg_may_create_pc($user, $type)) { |
| 944 | $available_types[] = l($type['name'], 'rpg/create/pc/' . $type['type']) . '<br />' . $type['shortdesc']; |
| 945 | } |
| 946 | } |
| 947 | $output .= theme('item_list', $available_types); |
| 948 | return $output; |
| 949 | } |
| 950 | |
| 951 | function rpg_form_object($object) { |
| 952 | // make sure we have all data loaded |
| 953 | if (!$object->is_new) { |
| 954 | $object = rpg_object($object, FALSE, TRUE); |
| 955 | } |
| 956 | |
| 957 | $form = array(); |
| 958 | |
| 959 | // TODO: make this a username lookup instead |
| 960 | $form['uid'] = array( |
| 961 | '#type' => 'value', |
| 962 | '#value' => $object->uid, |
| 963 | ); |
| 964 | $form['types'] = array( |
| 965 | '#type' => 'value', |
| 966 | '#value' => $object->types, |
| 967 | ); |
| 968 | if (user_access('administer rpg')) { |
| 969 | $options = array(); |
| 970 | foreach (rpg_types() as $type) { |
| 971 | $options[$type['type']] = $type['name']; |
| 972 | } |
| 973 | $form['types'] = array( |
| 974 | '#type' => 'select', |
| 975 | '#title' => t('Types'), |
| 976 | '#options' => $options, |
| 977 | '#default_value' => $object->types, |
| 978 | '#description' => t('Select the type(s) for this object. Note that conflicts may arise when using multiple types.'), |
| 979 | '#multiple' => TRUE, |
| 980 | ); |
| 981 | } |
| 982 | $form['created'] = array( |
| 983 | '#type' => 'value', |
| 984 | '#value' => $object->created, |
| 985 | ); |
| 986 | $form['is_new'] = array( |
| 987 | '#type' => 'value', |
| 988 | '#value' => $object->is_new, |
| 989 | ); |
| 990 | $form['rid'] = array( |
| 991 | '#type' => 'value', |
| 992 | '#value' => $object->rid, |
| 993 | ); |
| 994 | $form['data'] = array( |
| 995 | '#tree' => true, |
| 996 | ); |
| 997 | |
| 998 | if (is_array($object->data)) { |
| 999 | foreach ($object->data as $attr => $value) { |
| 1000 | $attribute = rpg_object_attributes($object->rid, $attr); |
| 1001 | $attribute['value'] = $value; |
| 1002 | $attribute['object'] = $object; |
| 1003 | $class = rpg_attribute_classes($attribute['class']); |
| 1004 | $form['data'][$attr] = module_invoke($class['module'], 'rpg_attribute_class_settings', 'form', $class['class'], $attribute); |
| 1005 | if (is_null($form['data'][$attr])) { |
| 1006 | // display our default form data |
| 1007 | $form['data'][$attr] = array( |
| 1008 | '#type' => 'textfield', |
| 1009 | '#title' => $attribute['name'], |
| 1010 | '#default_value' => $attribute['value'], |
| 1011 | '#description' => $attribute['description'], |
| 1012 | ); |
| 1013 | } |
| 1014 | $display = _rpg_call_function('form_display', $attr, $object->rid); |
| 1015 | if ($display === FALSE) { |
| 1016 | $form['data'][$attr]['#type'] = 'value'; |
| 1017 | $form['data'][$attr]['#value'] = $form['data'][$attr]['#default_value']; |
| 1018 | } |
| 1019 | } |
| 1020 | } |
| 1021 | |
| 1022 | $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 45); |
| 1023 | |
| 1024 | return $form; |
| 1025 | } |
| 1026 | |
| 1027 | // TODO: make sure inserts work ok |
| 1028 | function rpg_form_object_submit($form_id, $form_values) { |
| 1029 | if ($form_values['is_new']) { |
| 1030 | $object = rpg_create($form_values['types'], (array)$form_values['data']); |
| 1031 | } |
| 1032 | else { |
| 1033 | $object = array( |
| 1034 | 'types' => $form_values['types'], |
| 1035 | 'uid' => $form_values['uid'], |
| 1036 | 'created' => ($form_values['created'] ? $form_values['created'] : time()), |
| 1037 | 'changed' => time(), |
| 1038 | 'rid' => $form_values['rid'], |
| 1039 | 'data' => array(), |
| 1040 | ); |
| 1041 | |
| 1042 | $object = (object) $object; |
| 1043 | rpg_save_rpg($object);//print_r($form_values);//exit(); |
| 1044 | foreach(rpg_object_attributes($object) as $attribute) {//print_r($attribute); |
| 1045 | if (isset($form_values['data'][$attribute['attribute']])) {drupal_set_message('attr: ' . $attribute['attribute'].', '.$form_values['data'][$attribute['attribute']]); |
| 1046 | rpg_set($attribute['attribute'], $object, $form_values['data'][$attribute['attribute']]); |
| 1047 | } |
| 1048 | else if ($attribute['default_value']) {drupal_set_message('attr: '.$attribute['attribute'].', default: '.$attribute['default']); |
| 1049 | rpg_set($attribute['attribute'], $object, $attribute['default_value']); |
| 1050 | } |
| 1051 | } |
| 1052 | // foreach ((array)$form_values['data'] as $attr => $value) { |
| 1053 | // rpg_set($attr, $object, $value); |
| 1054 | // } |
| 1055 | } |
| 1056 | |
| 1057 | _rpg_save_all_marked_objects(); |
| 1058 | if (arg(2) == 'pc') { |
| 1059 | return 'rpg/select/' . $object->rid; |
| 1060 | } |
| 1061 | return 'rpg/view/' . $object->rid; |
| 1062 | } |
| 1063 | |
| 1064 | /** |
| 1065 | * creates a new rpg, saves it in the db, with assigned attribute values. then triggers on_create event and returns new object id |
| 1066 | */ |
| 1067 | function rpg_create($types = array(), $attributes = array()) { |
| 1068 | if (is_string($types)) { |
| 1069 | $types = (array) $types; |
| 1070 | } |
| 1071 | if (is_array($types) && !empty($types)) { |
| 1072 | $object = array( |
| 1073 | 'types' => $types, |
| 1074 | 'uid' => $user->uid, |
| 1075 | 'created' => time(), |
| 1076 | 'changed' => time(), |
| 1077 | 'data' => (array) $attributes, |
| 1078 | 'is_new' => TRUE, |
| 1079 | ); |
| 1080 | $object = _rpg_insert_new_rpg((object)$object); |
| 1081 | rpg_trigger('on_create', $object); |
| 1082 | return $object; |
| 1083 | } |
| 1084 | } |
| 1085 | |
| 1086 | /** |
| 1087 | * clones an object, making an identical copy. returns the new object, or NULL if failed |
| 1088 | */ |
| 1089 | function rpg_clone($object) { |
| 1090 | // load the full object to clone |
| 1091 | $object = rpg_object($object, FALSE, TRUE); |
| 1092 | if ($object->rid) { |
| 1093 | return rpg_create($object->types, $object->data); |
| 1094 | } |
| 1095 | } |
| 1096 | |
| 1097 | /** |
| 1098 | * returns true if the user has specific $op access to the $type |
| 1099 | * @param $op |
| 1100 | * 'create' => user may create objects of that type |
| 1101 | * 'edit' => user may edit any object of the type |
| 1102 | * 'edit own' => user may edit any object of the type they own |
| 1103 | * @param $type |
| 1104 | * the string or type array of the object type to create/edit |
| 1105 | * @return |
| 1106 | * true if allowed; false if not allowed |
| 1107 | */ |
| 1108 | function rpg_user_access($op, $type) { |
| 1109 | $return = user_access($op . ' rpg object') || user_access('admin rpg'); |
| 1110 | // TODO: add hooks for specific types |
| 1111 | return $return; |
| 1112 | } |
| 1113 | |
| 1114 | /** |
| 1115 | * is a user allowed to create a pc of the specific type? |
| 1116 | * we call this, because an admin might set certain user roles to have only a limited number of pc's |
| 1117 | * or maybe, for instance, only one of each race or class |
| 1118 | * @param $account |
| 1119 | * the user account to check |
| 1120 | * @param $type |
| 1121 | * the rpg type array to test |
| 1122 | * @return |
| 1123 | * true if the user may create a new pc of the type, false if not. |
| 1124 | */ |
| 1125 | function rpg_may_create_pc($account, $type) { |
| 1126 | if (!user_access('create pc rpg object')) { |
| 1127 | return false; |
| 1128 | } |
| 1129 | // TODO: call hooks to refine access |
| 1130 | return true; |
| 1131 | } |
| 1132 | |
| 1133 | /** |
| 1134 | * return a list of all available rpg types |
| 1135 | * @param $type |
| 1136 | * if given, just return the type specified by the string |
| 1137 | * otherwise, return an array of all types |
| 1138 | * @param $cached |
| 1139 | * if true, return the cached value, if it's cached. |
| 1140 | * otherwise, reload all the type data from include files |
| 1141 | */ |
| 1142 | function rpg_types($type = NULL, $cached = true) { |
| 1143 | static $types; |
| 1144 | |
| 1145 | // if it's a cachable request, try to load a cached value |
| 1146 | if (!isset($types) || !$cached) { |
| 1147 | if ($cached && $cache = cache_get('rpg_types', 'cache_rpg')) { |
| 1148 | $types = unserialize($cache->data); |
| 1149 | } |
| 1150 | else { |
| 1151 | // _rpg_type_load_types is in an external include |
| 1152 | rpg_include_loadcache(); |
| 1153 | |
| 1154 | $types = _rpg_type_load_types(); |
| 1155 | cache_set('rpg_types', 'cache_rpg', serialize($types)); |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | // just return the type we're looking for |
| 1160 | if (is_string($type)) { |
| 1161 | return $types[$type]; |
| 1162 | } |
| 1163 | else if (isset($type)) { |
| 1164 | return; |
| 1165 | } |
| 1166 | |
| 1167 | return $types; |
| 1168 | } |
| 1169 | |
| 1170 | /** |
| 1171 | * this will load all module-defined attribute classes, such as node, sprite, map, integer, string, and figured |
| 1172 | * TODO: cache this! |
| 1173 | * |
| 1174 | * @param $class |
| 1175 | * this will return just the specific class if specified. otherwise, it will return an array with all the classes. |
| 1176 | * @param $refresh |
| 1177 | * if set to true, it will force the list to be refreshed. |
| 1178 | */ |
| 1179 | function rpg_attribute_classes($class = NULL, $refresh = FALSE) { |
| 1180 | static $classes; |
| 1181 | if (!isset($classes) || $refresh) { |
| 1182 | $classes = array(); |
| 1183 | foreach (module_implements('rpg_attribute_class_settings') as $module) { |
| 1184 | $attributes = module_invoke($module, 'rpg_attribute_class_settings', 'info'); |
| 1185 | foreach ($attributes as $attribute_class => $info) { |
| 1186 | $info['class'] = $attribute_class; |
| 1187 | $info['module'] = $module; |
| 1188 | rpg_drupal_alter('rpg_class', $info); |
| 1189 | $classes[$attribute_class] = $info; |
| 1190 | } |
| 1191 | } |
| 1192 | } |
| 1193 | |
| 1194 | // just return the class we're looking for |
| 1195 | if ($class) { |
| 1196 | return $classes[$class]; |
| 1197 | } |
| 1198 | return $classes; |
| 1199 | } |
| 1200 | |
| 1201 | /** |
| 1202 | * load functions that rebuild cached arrays, such as rpg_types and attributes |
| 1203 | */ |
| 1204 | function rpg_include_loadcache() { |
| 1205 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.loadcache.inc'); |
| 1206 | } |
| 1207 | |
| 1208 | /** |
| 1209 | * load functions needed for admin pages |
| 1210 | */ |
| 1211 | function rpg_include_admin() { |
| 1212 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.admin.inc'); |
| 1213 | } |
| 1214 | |
| 1215 | /** |
| 1216 | * load functions needed for rpg object database, such as getting & setting object attributes to/from the db |
| 1217 | */ |
| 1218 | function rpg_include_db() { |
| 1219 | require_once(drupal_get_path('module', 'rpg') . '/inc/rpg.db.inc'); |
| 1220 | } |
| 1221 | |
| 1222 | function rpg_is_a($object, $type) { |
| 1223 | $object = rpg_object($object); |
| 1224 | foreach ((array)$object->types as $ancestor) { |
| 1225 | if (rpg_type_is_a($ancestor, $type)) { |
| 1226 | return true; |
| 1227 | } |
| 1228 | } |
| 1229 | return false; |
| 1230 | } |
| 1231 | |
| 1232 | /** |
| 1233 | * recursive function to check to see if a type has a specific ancestor |
| 1234 | * @param $type |
| 1235 | * string containing the type to check OR the array of a type returned by rpg_types($type) |
| 1236 | * @param $ancestor |
| 1237 | * string containing the type to see if we're an ancestor of |
| 1238 | */ |
| 1239 | function rpg_type_is_a($type, $ancestor) { |
| 1240 | if (is_string($type)) { |
| 1241 | $type = rpg_types($type); |
| 1242 | } |
| 1243 | if ($type['type'] == $ancestor) { |
| 1244 | return true; |
| 1245 | } |
| 1246 | foreach ((array)$type['parents'] as $parent) { |
| 1247 | if ($parent == $ancestor) { |
| 1248 | return true; |
| 1249 | } |
| 1250 |