static int check_lines() { int i,j; int total = 0; int lines = 0; for(i = 0; i < 4; i++) { if(row+i < 20) { for(j = 0; j < 14; j++) { total += grid[row+i][j]; } } if(total == 14) { lines++; copy_down(row+i, grid); trigger_event("LineCleared", (void*)row+i); } total = 0; } trigger_event("DoneClearing", (void*)row+i); return lines; }
static void new_block() { row = 0; col = 6; rot = 0; type = next_type; next_type = rand()%7; trigger_event("NewBlock", (void*)next_type); if(check_move()) trigger_event("GameOver", NULL); }
static void calc_score(int lines) { score = score + lines*10 * level; type = rand()%7; trigger_event("NewScore", (void*)score); total_lines += lines; if(total_lines >= 10) { level++; total_lines = 0; trigger_event("NewLevel", (void*)level); } }
static int move(int dir) { switch(dir) { case LEFT: col--; break; case RIGHT: col++; break; case DOWN: row++; break; case ROTATE: rot = (rot+1)%4; break; } int rc = check_move(); if(rc == 1) { switch(dir) { case LEFT: col++; break; case RIGHT: col--; break; case DOWN: row--; break; case ROTATE: rot = rot == 0 ? 3 : rot-1; break; } if(dir == DOWN) { cement_block(); trigger_event("BlockHit", NULL); int lines = check_lines(); if(lines) calc_score(lines); new_block(); } } else { trigger_event("MoveSucceeded", (void*)dir); } return rc; }
static void service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old) { struct service_instance *in_o = NULL, *in_n = NULL; if (node_old) in_o = container_of(node_old, struct service_instance, node); if (node_new) in_n = container_of(node_new, struct service_instance, node); if (in_o && in_n) { DEBUG(2, "Update instance %s::%s\n", in_o->srv->name, in_o->name); instance_update(in_o, in_n); instance_free(in_n); } else if (in_o) { DEBUG(2, "Free instance %s::%s\n", in_o->srv->name, in_o->name); instance_stop(in_o); instance_free(in_o); } else if (in_n) { DEBUG(2, "Create instance %s::%s\n", in_n->srv->name, in_n->name); instance_start(in_n); } blob_buf_init(&b, 0); trigger_event("instance.update", b.head); }
/** * periodically called by the main memcache loop. This will connect zookeeper if * necessary. Also, if the generation has changed (because of a zookeeper even), * it will then trigger data processing. */ void mc_zookeeper_tick() { ticker++; if (!zh) { LOG_DEBUG(("Connecting zookeeper...")); zh = zookeeper_init(settings.zookeeper_connect, process, 30000, &myid, 0, 0); if (!zh) { LOG_INFO(("Could not connect to zookeeper, error: %d", errno)); } else { LOG_DEBUG(("Zookeeper connection ok, status is %d", zoo_state(zh))); } trigger_event(); } if (connected) { long current_generation = generation; if (last_generation < current_generation) { LOG_DEBUG(("Tick (%d)", ticker)); int rc = zoo_aget_children(zh, settings.zookeeper_path, 1, node_completion, &ticker); if (rc != 0) { LOG_WARN(("Error %s while retrieving children!", zerror(rc))); } else { last_generation = current_generation; } } } }
/** * libevent handler for zookeeper events on the fd. */ static void zookeeper_event_handler(int fd, short event_type, void * arg) { int event_flags = 0; if (event_type & EV_READ) { LOG_DEBUG((" -> READ")); event_flags |= ZOOKEEPER_READ; } if (event_type & EV_WRITE) { LOG_DEBUG((" -> WRITE")); event_flags |= ZOOKEEPER_WRITE; } if (event_flags) { if (zh) { zookeeper_process(zh, event_flags); } else { LOG_INFO(("Event handler called with zh == null!")); } } else { LOG_DEBUG(("Called from timeout!")); } trigger_event(); }
/* Timer callback for @periodic_save_timer. As explained in @install_timer, * this function must erase the expired timer ID from all variables. */ static void periodic_save_handler(void *xxx) { static int periodic_save_event_id = EVENT_NONE; milliseconds_T interval; if (get_cmd_opt_bool((const unsigned char *)"anonymous")) return; /* Don't trigger anything at startup */ if (periodic_save_event_id == EVENT_NONE) set_event_id(periodic_save_event_id, (unsigned char *)"periodic-saving"); else trigger_event(periodic_save_event_id); interval = sec_to_ms(get_opt_int((const unsigned char *)"infofiles.save_interval", NULL)); if (!interval) { /* We should get here only if @periodic_save_handler * is being called from @periodic_save_change_hook or * @init_timer, rather than from the timer system. */ assert(periodic_save_timer == TIMER_ID_UNDEF); return; } install_timer(&periodic_save_timer, interval, periodic_save_handler, NULL); /* The expired timer ID has now been erased. */ }
void init_logic() { srand(time(NULL)); type = rand()%7; next_type = rand()%7; int types[2]; types[0] = type; types[1] = next_type; register_event_handler("AttemptMoveLeft", logic_AttemptMoveLeft); register_event_handler("AttemptMoveRight", logic_AttemptMoveRight); register_event_handler("AttemptMoveDown", logic_AttemptMoveDown); register_event_handler("BlockDrop", logic_BlockDrop); register_event_handler("AttemptBlockRotate", logic_AttemptBlockRotate); trigger_event("LogicReady", (void*)types); trigger_event("NewScore", 0); trigger_event("NewLevel", 1); }
inline void SoloScene::calculate_and_send_position() { TEXEngine::Core::Message parameters(3,0,0); parameters.add_integral_data(0,static_cast<TEXEngine::Core::MESSAGE_INTEGRAL_DATA_TYPE>(get_id())); parameters.add_integral_data(1,static_cast<TEXEngine::Core::MESSAGE_INTEGRAL_DATA_TYPE>(0)); parameters.add_integral_data(2,static_cast<TEXEngine::Core::MESSAGE_INTEGRAL_DATA_TYPE>(1)); trigger_event(PLAYER_POSITION,parameters); }
// ------------------------------------------------------------------------ // move the final step in the path // ------------------------------------------------------------------------ void t_army_mover::finish_path() { declare_timer( timer_1, "finish_path" ); end_move(); if (m_has_trigger || m_landing) { //////////////////////////////////////////////////////////// // replay functionality m_army->get_map()->record_look_trigger_event( m_army, m_trigger_point.direction ); //////////////////////////////////////////////////////////// m_army->turn_to( m_trigger_point.direction ); if (m_army->get_position() != m_trigger_point) { assert( m_army->get_position() == m_trigger_point.last_point ); expend_movement( m_trigger_point.move_cost ); } redraw_windows(); if (m_has_trigger) { assert( !m_landing ); declare_timer( timer_4, "Activate trigger" ); trigger_event(); activate_trigger(); } else { assert( m_army->is_boat() ); assert( m_landing ); m_army->leave_boat( m_trigger_point ); trigger_event(); } } else trigger_event(); on_end(); }
//void udb_serial_callback_received_byte(uint8_t rxchar) void mavlink_callback_received_byte(uint8_t rxchar) { // DPRINT("%u \r\n", rxchar); if (mavlink_parse_char(0, rxchar, &msg[mavlink_message_index], &r_mavlink_status)) { // Check that handling of previous message has completed before calling again if (handling_of_message_completed == true) { // Switch between incoming message buffers if (mavlink_message_index == 0) mavlink_message_index = 1; else mavlink_message_index = 0; handling_of_message_completed = false; trigger_event(mavlink_process_message_handle); } } }
// ------------------------------------------------------------------------ // class to move army on adventure map // ------------------------------------------------------------------------ void t_army_mover::cancel_move() { if (m_halted) return; t_counted_ptr<t_army_mover> ref = this; t_window_ptr frame = m_window->get_frame(); // temporary reference to prevent the adventure frame // from removing itself if the game is over end_move(); trigger_event(); if (m_has_trigger && m_army->get_position() == m_trigger_point) activate_trigger(); on_end(); }
// ------------------------------------------------------------------------ // do movement that's hidden // ------------------------------------------------------------------------ void t_army_mover::do_hidden_move() { if (m_is_visible) return; if (m_path.size() == 0) { finish_path(); return; } t_adventure_map const& map = *m_army->get_map(); t_player& player = map.get_player(); int team = player.get_team(); declare_timer( timer_1, "do_hidden_movement" ); while (!m_is_visible && !m_halted) { t_adventure_path_point& point = m_path[m_step]; m_army->move( point ); expend_movement( point.move_cost ); mark_eluded_armies(); if (m_step == m_path.size() - 1) { finish_path(); return; } trigger_event(); if (m_halted) return; m_is_visible = !m_army->hidden_by_fog_of_war( team ) && show_enemy_moves(); if (m_is_visible) break; // break here, because start_new_square will increment step. ++m_step; declare_timer( timer_2, "on_starting_new_square: hidden" ); on_starting_new_square(); } if (m_halted) return; m_army->set_action( k_adv_actor_action_walk ); m_distance = compute_overall_distance( m_path, m_step + 1 ); start_new_square(); prepare_move( 0 ); set_next_time( get_time() + get_delay() ); }
struct uri * get_proxy_uri(struct uri *uri, struct connection_state *error_state) { if (uri->protocol == PROTOCOL_PROXY) { return get_composed_uri(uri, URI_BASE); } else { #ifdef CONFIG_SCRIPTING unsigned char *tmp = NULL; static int get_proxy_event_id = EVENT_NONE; set_event_id(get_proxy_event_id, "get-proxy"); trigger_event(get_proxy_event_id, &tmp, struri(uri)); uri = get_proxy_worker(uri, tmp, error_state); mem_free_if(tmp); return uri; #else return get_proxy_worker(uri, NULL, error_state); #endif } }
/** * Drop an object onto the floor. * @param op Player object. * @param tmp The object to drop. * @param nrof Number of items to drop (0 for all). */ void drop_object(object *op, object *tmp, long nrof) { object *floor; if (QUERY_FLAG(tmp, FLAG_NO_DROP) && !QUERY_FLAG(op, FLAG_WIZ)) { return; } if (op->type == PLAYER) { CONTR(op)->praying = 0; } if (QUERY_FLAG(tmp, FLAG_APPLIED)) { /* Can't unapply it */ if (apply_special(op, tmp, AP_UNAPPLY | AP_NO_MERGE)) { return; } } if (tmp->type == CONTAINER) { container_unlink(NULL, tmp); } /* Trigger the DROP event */ if (trigger_event(EVENT_DROP, op, tmp, NULL, NULL, nrof, 0, 0, SCRIPT_FIX_ACTIVATOR)) { return; } /* We are only dropping some of the items. We split the current * object off. */ if (nrof && tmp->nrof != (uint32) nrof) { object *tmp2 = tmp, *tmp2_cont = tmp->env; tag_t tmp2_tag = tmp2->count; char err[MAX_BUF]; tmp = get_split_ob(tmp, nrof, err, sizeof(err)); if (!tmp) { new_draw_info(NDI_UNIQUE, op, err); return; } /* Tell the client what happened to the rest of the objects. tmp2 * is now the original object */ if (op->type == PLAYER) { if (was_destroyed(tmp2, tmp2_tag)) { esrv_del_item(CONTR(op), tmp2_tag, tmp2_cont); } else { esrv_send_item(op, tmp2); } } } else { remove_ob(tmp); if (check_walk_off(tmp, NULL, MOVE_APPLY_DEFAULT) != CHECK_WALK_OK) { return; } } if (QUERY_FLAG(tmp, FLAG_STARTEQUIP) || QUERY_FLAG(tmp, FLAG_UNPAID)) { if (op->type == PLAYER) { new_draw_info_format(NDI_UNIQUE, op, "You drop the %s.", query_name(tmp, NULL)); esrv_del_item(CONTR(op), tmp->count, tmp->env); if (QUERY_FLAG(tmp, FLAG_UNPAID)) { new_draw_info(NDI_UNIQUE, op, "The shop magic put it back to the storage."); floor = GET_MAP_OB_LAYER(op->map, op->x, op->y, 0); /* If the player is standing on a unique shop floor or unique randomitems shop floor, drop the object back to the floor */ if (floor && floor->type == SHOP_FLOOR && (QUERY_FLAG(floor, FLAG_IS_MAGICAL) || (floor->randomitems && QUERY_FLAG(floor, FLAG_CURSED)))) { tmp->x = op->x; tmp->y = op->y; insert_ob_in_map(tmp, op->map, op, 0); } } else { new_draw_info(NDI_UNIQUE, op, "The god-given item vanishes to nowhere as you drop it!"); } } fix_player(op); return; } /* If SAVE_INTERVAL is commented out, we never want to save * the player here. */ #ifdef SAVE_INTERVAL if (op->type == PLAYER && !QUERY_FLAG(tmp, FLAG_UNPAID) && (tmp->nrof ? tmp->value * tmp->nrof : tmp->value > 2000) && (CONTR(op)->last_save_time + SAVE_INTERVAL) <= time(NULL)) { save_player(op, 1); CONTR(op)->last_save_time = time(NULL); } #endif floor = GET_MAP_OB_LAYER(op->map, op->x, op->y, 0); if (floor && floor->type == SHOP_FLOOR && !QUERY_FLAG(tmp, FLAG_UNPAID) && tmp->type != MONEY) { sell_item(tmp, op, -1); /* Ok, we have really sold it - not only dropped. Run this only * if the floor is not magical (i.e., unique shop) */ if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(floor, FLAG_IS_MAGICAL)) { if (op->type == PLAYER) { new_draw_info(NDI_UNIQUE, op, "The shop magic put it to the storage."); esrv_del_item(CONTR(op), tmp->count, tmp->env); } fix_player(op); if (op->type == PLAYER) { esrv_send_item(op, op); } return; } } tmp->x = op->x; tmp->y = op->y; if (op->type == PLAYER) { esrv_del_item(CONTR(op), tmp->count, tmp->env); } insert_ob_in_map(tmp, op->map, op, 0); SET_FLAG(op, FLAG_NO_APPLY); remove_ob(op); insert_ob_in_map(op, op->map, op, INS_NO_MERGE | INS_NO_WALK_ON); CLEAR_FLAG(op, FLAG_NO_APPLY); /* Need to update the weight for the player */ if (op->type == PLAYER) { fix_player(op); esrv_send_item(op, op); } }
// Low priority service routine trigger inline void data_services_trigger(void) { trigger_event(data_service_event_handle); }
void PSPControllerDevice::update( const unsigned long id ) { Core::Message parameters(5,0,0); int difference_x = 0; int difference_y = 0; parameters.add_integral_data(0,id); parameters.add_integral_data(2,0); memcpy(&this->_previous_button_state,&this->_current_button_state,sizeof(SceCtrlData)); sceCtrlPeekBufferPositive(&this->_current_button_state,1); parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_button_state.Lx)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_button_state.Ly)); trigger_event(Core::PSP_CONTROLLER_STICK_POSITION,parameters); difference_x = this->_current_button_state.Lx - this->_previous_button_state.Lx; difference_y = this->_current_button_state.Ly - this->_previous_button_state.Ly; if ( std::abs(difference_x) > _deadzone || std::abs(difference_y) > _deadzone ) { parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_x)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_y)); trigger_event(Core::PSP_CONTROLLER_STICK_POSITION_CHANGED,parameters); } if ( this->_current_button_state.Buttons != this->_previous_button_state.Buttons ) { int select = (this->_current_button_state.Buttons & SCE_CTRL_SELECT) - (this->_previous_button_state.Buttons & SCE_CTRL_SELECT); int start = (this->_current_button_state.Buttons & SCE_CTRL_START) - (this->_previous_button_state.Buttons & SCE_CTRL_START); int up = (this->_current_button_state.Buttons & SCE_CTRL_UP) -( this->_previous_button_state.Buttons & SCE_CTRL_UP); int right = (this->_current_button_state.Buttons & SCE_CTRL_RIGHT) - (this->_previous_button_state.Buttons & SCE_CTRL_RIGHT); int down = (this->_current_button_state.Buttons & SCE_CTRL_DOWN) - (this->_previous_button_state.Buttons & SCE_CTRL_DOWN); int left = (this->_current_button_state.Buttons & SCE_CTRL_LEFT) - (this->_previous_button_state.Buttons & SCE_CTRL_LEFT); int L = (this->_current_button_state.Buttons & SCE_CTRL_L) - (this->_previous_button_state.Buttons & SCE_CTRL_L); int R = (this->_current_button_state.Buttons & SCE_CTRL_R) - (this->_previous_button_state.Buttons & SCE_CTRL_R); int triangle = (this->_current_button_state.Buttons & SCE_CTRL_TRIANGLE) - (this->_previous_button_state.Buttons & SCE_CTRL_TRIANGLE); int circle = (this->_current_button_state.Buttons & SCE_CTRL_CIRCLE) - (this->_previous_button_state.Buttons & SCE_CTRL_CIRCLE); int cross = (this->_current_button_state.Buttons & SCE_CTRL_CROSS) - (this->_previous_button_state.Buttons & SCE_CTRL_CROSS); int square= (this->_current_button_state.Buttons & SCE_CTRL_SQUARE) - (this->_previous_button_state.Buttons & SCE_CTRL_SQUARE); parameters.add_integral_data(3,0); parameters.add_integral_data(4,0); if ( select < 0 ) trigger_event(Core::PSP_CONTROLLER_SELECT_UP,parameters); else if ( select > 0 ) trigger_event(Core::PSP_CONTROLLER_SELECT_DOWN,parameters); if ( start < 0 ) trigger_event(Core::PSP_CONTROLLER_START_UP,parameters); else if ( start > 0 ) trigger_event(Core::PSP_CONTROLLER_START_DOWN,parameters); if ( up < 0 ) trigger_event(Core::PSP_CONTROLLER_UPARROW_UP,parameters); else if ( up > 0 ) trigger_event(Core::PSP_CONTROLLER_UPARROW_DOWN,parameters); if ( right < 0 ) trigger_event(Core::PSP_CONTROLLER_RIGHTARROW_UP,parameters); else if ( right > 0 ) trigger_event(Core::PSP_CONTROLLER_RIGHTARROW_DOWN,parameters); if ( down < 0 ) trigger_event(Core::PSP_CONTROLLER_DOWNARROW_UP,parameters); else if ( down > 0 ) trigger_event(Core::PSP_CONTROLLER_DOWNARROW_DOWN,parameters); if ( left < 0 ) trigger_event(Core::PSP_CONTROLLER_LEFTARROW_UP,parameters); else if ( left > 0 ) trigger_event(Core::PSP_CONTROLLER_LEFTARROW_DOWN,parameters); if ( L < 0 ) trigger_event(Core::PSP_CONTROLLER_LEFTTRIGGER_UP,parameters); else if ( L > 0 ) trigger_event(Core::PSP_CONTROLLER_LEFTTRIGGER_DOWN,parameters); if ( R < 0 ) trigger_event(Core::PSP_CONTROLLER_RIGHTTRIGGER_UP,parameters); else if ( R > 0 ) trigger_event(Core::PSP_CONTROLLER_RIGHTTRIGGER_DOWN,parameters); if ( triangle < 0 ) trigger_event(Core::PSP_CONTROLLER_TRIANGLE_UP,parameters); else if ( triangle > 0 ) trigger_event(Core::PSP_CONTROLLER_TRIANGLE_DOWN,parameters); if ( circle < 0 ) trigger_event(Core::PSP_CONTROLLER_CIRCLE_UP,parameters); else if ( circle > 0 ) trigger_event(Core::PSP_CONTROLLER_CIRCLE_DOWN,parameters); if ( cross < 0 ) trigger_event(Core::PSP_CONTROLLER_CROSS_UP,parameters); else if ( cross > 0 ) trigger_event(Core::PSP_CONTROLLER_CROSS_DOWN,parameters); if ( square < 0 ) trigger_event(Core::PSP_CONTROLLER_SQUARE_UP,parameters); else if ( square > 0 ) trigger_event(Core::PSP_CONTROLLER_SQUARE_DOWN,parameters); } };
/** * Op throws any object toss_item. * @param op Living thing throwing something. * @param toss_item Item thrown. * @param dir Direction to throw. */ void do_throw(object *op, object *toss_item, int dir) { object *left_cont, *throw_ob = toss_item, *left = NULL, *tmp_op; tag_t left_tag; rv_vector range_vector; if (!throw_ob) { if (op->type == PLAYER) { new_draw_info(NDI_UNIQUE, op, "You have nothing to throw."); } return; } if (QUERY_FLAG(throw_ob, FLAG_STARTEQUIP)) { if (op->type == PLAYER) { new_draw_info(NDI_UNIQUE, op, "The gods won't let you throw that."); } return; } if (throw_ob->weight <= 0) { new_draw_info_format(NDI_UNIQUE, op, "You can't throw %s.\n", query_base_name(throw_ob, NULL)); return; } /* These are throwing objects left to the player */ left = throw_ob; left_cont = left->env; left_tag = left->count; /* Sometimes get_split_ob can't split an object (because op->nrof==0?) * and returns NULL. We must use 'left' then */ if ((throw_ob = get_split_ob(throw_ob, 1, NULL, 0)) == NULL) { throw_ob = left; remove_ob(left); check_walk_off(left, NULL, MOVE_APPLY_VANISHED); if (op->type == PLAYER) { esrv_del_item(CONTR(op), left->count, left->env); } } else if (op->type == PLAYER) { if (was_destroyed(left, left_tag)) { esrv_del_item(CONTR(op), left_tag, left_cont); } else { esrv_update_item(UPD_NROF, op, left); } } /* Special case: throwing powdery substances like dust, dirt */ if (QUERY_FLAG(throw_ob, FLAG_DUST)) { cast_dust(op, throw_ob, dir); /* update the shooting speed for the player action timer. * We init the used skill with it - its not calculated here. * cast_dust() can change the used skill... */ if (op->type == PLAYER) { op->chosen_skill->stats.maxsp = throw_ob->last_grace; } return; } /* Targetting throwing */ if (!dir && op->type == PLAYER && OBJECT_VALID(CONTR(op)->target_object, CONTR(op)->target_object_count)) { dir = get_dir_to_target(op, CONTR(op)->target_object, &range_vector); } /* Three things here prevent a throw, you aimed at your feet, you * have no effective throwing strength, or you threw at a wall */ if (!dir || wall(op->map, op->x + freearr_x[dir], op->y + freearr_y[dir])) { /* Bounces off 'wall', and drops to feet */ if (!QUERY_FLAG(throw_ob, FLAG_REMOVED)) { remove_ob(throw_ob); if (check_walk_off(throw_ob, NULL, MOVE_APPLY_MOVE) != CHECK_WALK_OK) { return; } } throw_ob->x = op->x; throw_ob->y = op->y; if (!insert_ob_in_map(throw_ob, op->map, op, 0)) { return; } if (op->type == PLAYER) { if (!dir) { new_draw_info_format(NDI_UNIQUE, op, "You drop %s at the ground.", query_name(throw_ob, NULL)); } else { new_draw_info(NDI_UNIQUE, op, "Something is in the way."); } } return; } set_owner(throw_ob, op); set_owner(throw_ob->inv, op); throw_ob->direction = dir; throw_ob->x = op->x; throw_ob->y = op->y; /* Save original wc and dam */ throw_ob->last_heal = throw_ob->stats.wc; throw_ob->stats.hp = throw_ob->stats.dam; /* Speed */ throw_ob->speed = MIN(1.0f, (speed_bonus[op->stats.Str] + 1.0f) / 1.5f); /* Now we get the wc from the used skill. */ if ((tmp_op = SK_skill(op))) { throw_ob->stats.wc += tmp_op->last_heal; } /* Monsters */ else { throw_ob->stats.wc += 10; } throw_ob->stats.wc_range = op->stats.wc_range; if (QUERY_FLAG(throw_ob, FLAG_IS_THROWN)) { throw_ob->stats.dam += throw_ob->magic; throw_ob->stats.wc += throw_ob->magic; /* Adjust for players */ if (op->type == PLAYER) { op->chosen_skill->stats.maxsp = throw_ob->last_grace; throw_ob->stats.dam = FABS((int) ((float) (throw_ob->stats.dam + dam_bonus[op->stats.Str] / 2) * LEVEL_DAMAGE(SK_level(op)))); throw_ob->stats.wc += thaco_bonus[op->stats.Dex] + SK_level(op); } else { throw_ob->stats.dam = FABS((int) ((float) (throw_ob->stats.dam) * LEVEL_DAMAGE(op->level))); throw_ob->stats.wc += 10 + op->level; } throw_ob->stats.grace = throw_ob->last_sp; throw_ob->stats.maxgrace = 60 + (RANDOM() % 12); /* Only throw objects get directional faces */ if (GET_ANIM_ID(throw_ob) && NUM_ANIMATIONS(throw_ob)) { SET_ANIMATION(throw_ob, (NUM_ANIMATIONS(throw_ob) / NUM_FACINGS(throw_ob)) * dir); } /* Adjust damage with item condition */ throw_ob->stats.dam = (sint16) (((float) throw_ob->stats.dam / 100.0f) * (float) throw_ob->item_condition); } if (throw_ob->stats.dam < 0) { throw_ob->stats.dam = 0; } update_ob_speed(throw_ob); throw_ob->speed_left = 0; SET_MULTI_FLAG(throw_ob, FLAG_FLYING); SET_FLAG(throw_ob, FLAG_FLY_ON); SET_FLAG(throw_ob, FLAG_WALK_ON); play_sound_map(op->map, CMD_SOUND_EFFECT, "throw.ogg", op->x, op->y, 0, 0); /* Trigger the THROW event */ trigger_event(EVENT_THROW, op, throw_ob, NULL, NULL, 0, 0, 0, SCRIPT_FIX_ACTIVATOR); if (insert_ob_in_map(throw_ob, op->map, op, 0)) { move_arrow(throw_ob); } }
/** * 'victim' moves onto 'trap' (trap has FLAG_WALK_ON or FLAG_FLY_ON set) or * 'victim' leaves 'trap' (trap has FLAG_WALK_OFF or FLAG_FLY_OFF) set. * * I added the flags parameter to give the single events more information * about whats going on: * * Most important is the "MOVE_APPLY_VANISHED" flag. * If set, a object has left a tile but "vanished" and not moved (perhaps * it exploded or something). This means that some events are not * triggered like trapdoors or teleporter traps for example which have a * "FLY/MOVE_OFF" set. This will avoid that they touch invalid objects. * @param trap Object victim moved on. * @param victim The object that moved on trap. * @param originator Player, monster or other object that caused 'victim' * to move onto 'trap'. Will receive messages caused by this action. May * be NULL, however, some types of traps require an originator to * function. * @param flags Flags. */ void move_apply(object *trap, object *victim, object *originator, int flags) { static int recursion_depth = 0; /* move_apply() is the most likely candidate for causing unwanted and * possibly unlimited recursion. */ /* The following was changed because it was causing perfeclty correct * maps to fail. 1) it's not an error to recurse: * rune detonates, summoning monster. monster lands on nearby rune. * nearby rune detonates. This sort of recursion is expected and * proper. This code was causing needless crashes. */ if (recursion_depth >= 500) { LOG(llevDebug, "WARNING: move_apply(): aborting recursion [trap arch %s, name %s; victim arch %s, name %s]\n", trap->arch->name, trap->name, victim->arch->name, victim->name); return; } if (trap->head) { trap = trap->head; } /* Trigger the TRIGGER event */ if (trigger_event(EVENT_TRIGGER, victim, trap, originator, NULL, 0, 0, 0, SCRIPT_FIX_NOTHING)) { return; } recursion_depth++; switch (trap->type) { /* these objects can trigger other objects connected to them. * We need to check them at map loading time and other special * events to be sure to have a 100% working map state. */ case BUTTON: case PEDESTAL: update_button(trap); break; case TRIGGER_BUTTON: case TRIGGER_PEDESTAL: case TRIGGER_ALTAR: check_trigger(trap, victim); break; case CHECK_INV: check_inv(victim, trap); break; /* these objects trigger to but they are "instant". * We don't need to check them when loading. */ case ALTAR: /* sacrifice victim on trap */ apply_altar(trap, victim, originator); break; case CONVERTER: if (!(flags & MOVE_APPLY_VANISHED)) { convert_item(victim, trap); } break; case PLAYERMOVER: break; /* should be walk_on/fly_on only */ case SPINNER: if (victim->direction) { if ((victim->direction = victim->direction + trap->direction) > 8) { victim->direction = (victim->direction % 8) + 1; } update_turn_face(victim); } break; case DIRECTOR: if (victim->direction) { victim->direction = trap->direction; update_turn_face(victim); } break; /* no need to hit anything */ case MMISSILE: if (IS_LIVE(victim) && !(flags&MOVE_APPLY_VANISHED)) { tag_t trap_tag = trap->count; hit_player(victim, trap->stats.dam, trap, AT_MAGIC); if (!was_destroyed(trap, trap_tag)) { remove_ob(trap); } check_walk_off(trap, NULL, MOVE_APPLY_VANISHED); } break; case THROWN_OBJ: if (trap->inv == NULL || (flags & MOVE_APPLY_VANISHED)) { break; } /* fallthrough */ case ARROW: /* bad bug: monster throw a object, make a step forwards, step on object , * trigger this here and get hit by own missile - and will be own enemy. * Victim then is his own enemy and will start to kill herself (this is * removed) but we have not synced victim and his missile. To avoid senseless * action, we avoid hits here */ if ((IS_LIVE(victim) && trap->speed) && trap->owner != victim) { hit_with_arrow(trap, victim); } break; case CONE: case LIGHTNING: break; case BULLET: if ((QUERY_FLAG(victim, FLAG_NO_PASS) || IS_LIVE(victim)) && !(flags & MOVE_APPLY_VANISHED)) { check_fired_arch(trap); } break; case TRAPDOOR: { int max, sound_was_played; object *ab; if ((flags & MOVE_APPLY_VANISHED)) { break; } if (!trap->value) { sint32 tot; for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above) { if (!QUERY_FLAG(ab, FLAG_FLYING)) { tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying; } } if (!(trap->value = (tot > trap->weight) ? 1 : 0)) { break; } SET_ANIMATION(trap, (NUM_ANIMATIONS(trap) / NUM_FACINGS(trap)) * trap->direction + trap->value); update_object(trap, UP_OBJ_FACE); } for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab && !QUERY_FLAG(ab, FLAG_FLYING); ab = ab->above) { if (!sound_was_played) { play_sound_map(trap->map, trap->x, trap->y, SOUND_FALL_HOLE, SOUND_NORMAL); sound_was_played = 1; } if (ab->type == PLAYER) { new_draw_info(NDI_UNIQUE, ab, "You fall into a trapdoor!"); } transfer_ob(ab, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, ab, trap); } break; } case PIT: /* Pit not open? */ if ((flags & MOVE_APPLY_VANISHED) || trap->stats.wc > 0) { break; } play_sound_map(victim->map, victim->x, victim->y, SOUND_FALL_HOLE, SOUND_NORMAL); if (victim->type == PLAYER) { new_draw_info(NDI_UNIQUE, victim, "You fall through the hole!\n"); } transfer_ob(victim->head ? victim->head : victim, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, victim, trap); break; case EXIT: /* If no map path specified, we assume it is the map path of the exit. */ if (!EXIT_PATH(trap)) { FREE_AND_ADD_REF_HASH(EXIT_PATH(trap), trap->map->path); } if (!(flags & MOVE_APPLY_VANISHED) && victim->type == PLAYER && EXIT_PATH(trap) && EXIT_Y(trap) != -1 && EXIT_X(trap) != -1) { /* Basically, don't show exits leading to random maps the players output. */ if (trap->msg && strncmp(EXIT_PATH(trap), "/!", 2) && strncmp(EXIT_PATH(trap), "/random/", 8)) { new_draw_info(NDI_NAVY, victim, trap->msg); } enter_exit(victim, trap); } break; case SHOP_MAT: if (!(flags & MOVE_APPLY_VANISHED)) { apply_shop_mat(trap, victim); } break; /* Drop a certain amount of gold, and have one item identified */ case IDENTIFY_ALTAR: if (!(flags & MOVE_APPLY_VANISHED)) { apply_identify_altar(victim, trap, originator); } break; case SIGN: /* Only player should be able read signs */ if (victim->type == PLAYER) { apply_sign(victim, trap); } break; case CONTAINER: if (victim->type == PLAYER) { (void) esrv_apply_container(victim, trap); } break; case RUNE: if (!(flags & MOVE_APPLY_VANISHED) && trap->level && IS_LIVE(victim)) { spring_trap(trap, victim); } break; #if 0 /* we don't have this atm. */ case DEEP_SWAMP: if (!(flags & MOVE_APPLY_VANISHED)) { walk_on_deep_swamp(trap, victim); } break; #endif default: LOG(llevDebug, "name %s, arch %s, type %d with fly/walk on/off not handled in move_apply()\n", trap->name, trap->arch->name, trap->type); break; } recursion_depth--; }
/** * Main apply handler. * * Checks for unpaid items before applying. * @param op ::object causing tmp to be applied. * @param tmp ::object being applied. * @param aflag Special (always apply/unapply) flags. Nothing is done * with them in this function - they are passed to apply_special(). * @retval 0 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. */ int manual_apply(object *op, object *tmp, int aflag) { if (tmp->head) { tmp = tmp->head; } if (op->type == PLAYER) { CONTR(op)->praying = 0; } if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED)) { if (op->type == PLAYER) { new_draw_info(NDI_UNIQUE, op, "You should pay for it first."); return 1; } /* Monsters just skip unpaid items */ else { return 0; } } /* Monsters must not apply random chests, nor magic_mouths with a counter */ if (op->type != PLAYER && tmp->type == TREASURE) { return 0; } /* Trigger the APPLY event */ if (!(aflag & AP_NO_EVENT) && trigger_event(EVENT_APPLY, op, tmp, NULL, NULL, aflag, 0, 0, SCRIPT_FIX_ACTIVATOR)) { return 1; } aflag &= ~AP_NO_EVENT; /* Control apply by controling a set exp object level or player exp level */ if (tmp->item_level) { int tmp_lev; if (tmp->item_skill) { tmp_lev = find_skill_exp_level(op, tmp->item_skill); } else { tmp_lev = op->level; } if (tmp->item_level > tmp_lev) { new_draw_info(NDI_UNIQUE, op, "The item level is too high to apply."); return 1; } } switch (tmp->type) { case HOLY_ALTAR: new_draw_info_format(NDI_UNIQUE, op, "You touch the %s.", tmp->name); if (change_skill(op, SK_PRAYING)) { pray_at_altar(op, tmp); } else { new_draw_info(NDI_UNIQUE, op, "Nothing happens. It seems you miss the right skill."); } return 1; break; case HANDLE: new_draw_info(NDI_UNIQUE, op, "You turn the handle."); play_sound_map(op->map, op->x, op->y, SOUND_TURN_HANDLE, SOUND_NORMAL); tmp->value = tmp->value ? 0 : 1; SET_ANIMATION(tmp, ((NUM_ANIMATIONS(tmp) / NUM_FACINGS(tmp)) * tmp->direction) + tmp->value); update_object(tmp, UP_OBJ_FACE); push_button(tmp); return 1; case TRIGGER: if (check_trigger(tmp, op)) { new_draw_info(NDI_UNIQUE, op, "You turn the handle."); play_sound_map(tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE, SOUND_NORMAL); } else { new_draw_info(NDI_UNIQUE, op, "The handle doesn't move."); } return 1; case EXIT: if (op->type != PLAYER || !tmp->map) { return 0; } /* If no map path specified, we assume it is the map path of the exit. */ if (!EXIT_PATH(tmp)) { FREE_AND_ADD_REF_HASH(EXIT_PATH(tmp), tmp->map->path); } if (!EXIT_PATH(tmp) || !is_legal_2ways_exit(op, tmp) || (EXIT_Y(tmp) == -1 && EXIT_X(tmp) == -1)) { new_draw_info_format(NDI_UNIQUE, op, "The %s is closed.", query_name(tmp, NULL)); } else { /* Don't display messages for random maps. */ if (tmp->msg && strncmp(EXIT_PATH(tmp), "/!", 2) && strncmp(EXIT_PATH(tmp), "/random/", 8)) { new_draw_info(NDI_NAVY, op, tmp->msg); } enter_exit(op, tmp); } return 1; case SIGN: apply_sign(op, tmp); return 1; case BOOK: if (op->type == PLAYER) { apply_book(op, tmp); return 1; } return 0; case SKILLSCROLL: if (op->type == PLAYER) { apply_skillscroll(op, tmp); return 1; } return 0; case SPELLBOOK: if (op->type == PLAYER) { apply_spellbook(op, tmp); return 1; } return 0; case SCROLL: apply_scroll(op, tmp); return 1; case POTION: (void) apply_potion(op, tmp); return 1; case LIGHT_APPLY: apply_player_light(op, tmp); return 1; case LIGHT_REFILL: apply_player_light_refill(op, tmp); return 1; /* Eneq(@csd.uu.se): Handle apply on containers. */ case CLOSE_CON: if (op->type == PLAYER) { (void) esrv_apply_container(op, tmp->env); } return 1; case CONTAINER: if (op->type == PLAYER) { (void) esrv_apply_container(op, tmp); } return 1; case TREASURE: apply_treasure(op, tmp); return 1; case WEAPON: case ARMOUR: case BOOTS: case GLOVES: case AMULET: case GIRDLE: case BRACERS: case SHIELD: case HELMET: case RING: case CLOAK: case WAND: case ROD: case HORN: case SKILL: case BOW: case SKILL_ITEM: /* Not in inventory */ if (tmp->env != op) { return 2; } (void) apply_special(op, tmp, aflag); return 1; case DRINK: case FOOD: case FLESH: apply_food(op, tmp); return 1; case POISON: apply_poison(op, tmp); return 1; case SAVEBED: if (op->type == PLAYER) { apply_savebed(op); return 1; } return 0; case ARMOUR_IMPROVER: if (op->type == PLAYER) { apply_armour_improver(op, tmp); return 1; } return 0; case WEAPON_IMPROVER: apply_weapon_improver(op, tmp); return 1; case CLOCK: if (op->type == PLAYER) { timeofday_t tod; get_tod(&tod); new_draw_info_format(NDI_UNIQUE, op, "It is %d minute%s past %d o'clock %s", tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), ((tod.hour % (HOURS_PER_DAY / 2) == 0) ? (HOURS_PER_DAY / 2) : ((tod.hour) % (HOURS_PER_DAY / 2))), ((tod.hour >= (HOURS_PER_DAY / 2)) ? "pm" : "am")); return 1; } return 0; case POWER_CRYSTAL: apply_power_crystal(op, tmp); return 1; /* For lighting torches/lanterns/etc */ case LIGHTER: if (op->type == PLAYER) { apply_lighter(op, tmp); return 1; } return 0; /* So the below default case doesn't execute for these objects, * even if they have message. */ case DOOR: return 0; /* Nothing from the above... but show a message if it has one. */ default: if (tmp->msg) { new_draw_info(NDI_UNIQUE, op, tmp->msg); return 1; } return 0; } }
void create() { seteuid(getuid()); message("channel:sys", HIR"【自然奇观】峨嵋金顶日出。\n"NOR, users()); trigger_event(); }
isc_result_t omapi_one_dispatch (omapi_object_t *wo, struct timeval *t) { fd_set r, w, x, rr, ww, xx; int max = 0; int count; int desc; struct timeval now, to; omapi_io_object_t *io, *prev, *next; omapi_waiter_object_t *waiter; omapi_object_t *tmp = (omapi_object_t *)0; isc_result_t status; if (!wo || wo -> type != omapi_type_waiter) waiter = (omapi_waiter_object_t *)0; else waiter = (omapi_waiter_object_t *)wo; FD_ZERO (&x); /* First, see if the timeout has expired, and if so return. */ if (t) { gettimeofday (&now, (struct timezone *)0); cur_tv.tv_sec = now.tv_sec; cur_tv.tv_usec = now.tv_usec; if (now.tv_sec > t -> tv_sec || (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec)) return ISC_R_TIMEDOUT; /* We didn't time out, so figure out how long until we do. */ to.tv_sec = t -> tv_sec - now.tv_sec; to.tv_usec = t -> tv_usec - now.tv_usec; if (to.tv_usec < 0) { to.tv_usec += 1000000; to.tv_sec--; } /* It is possible for the timeout to get set larger than the largest time select() is willing to accept. Restricting the timeout to a maximum of one day should work around this. -DPN. (Ref: Bug #416) */ if (to.tv_sec > (60 * 60 * 24)) to.tv_sec = 60 * 60 * 24; } /* If the object we're waiting on has reached completion, return now. */ if (waiter && waiter -> ready) return ISC_R_SUCCESS; again: /* If we have no I/O state, we can't proceed. */ if (!(io = omapi_io_states.next)) return ISC_R_NOMORE; /* Set up the read and write masks. */ FD_ZERO (&r); FD_ZERO (&w); for (; io; io = io -> next) { /* Check for a read socket. If we shouldn't be trying to read for this I/O object, either there won't be a readfd function, or it'll return -1. */ if (io -> readfd && io -> inner && (desc = (*(io -> readfd)) (io -> inner)) >= 0) { FD_SET (desc, &r); if (desc > max) max = desc; } /* Same deal for write fdets. */ if (io -> writefd && io -> inner && (desc = (*(io -> writefd)) (io -> inner)) >= 0) { FD_SET (desc, &w); if (desc > max) max = desc; } } /* poll if all reader are dry */ now.tv_sec = 0; now.tv_usec = 0; rr=r; ww=w; xx=x; /* poll once */ count = select(max + 1, &r, &w, &x, &now); if (!count) { /* We are dry now */ trigger_event(&rw_queue_empty); /* Wait for a packet or a timeout... XXX */ r = rr; w = ww; x = xx; count = select(max + 1, &r, &w, &x, t ? &to : NULL); } /* Get the current time... */ gettimeofday (&cur_tv, (struct timezone *)0); /* We probably have a bad file descriptor. Figure out which one. When we find it, call the reaper function on it, which will maybe make it go away, and then try again. */ if (count < 0) { struct timeval t0; omapi_io_object_t *prev = (omapi_io_object_t *)0; io = (omapi_io_object_t *)0; if (omapi_io_states.next) omapi_io_reference (&io, omapi_io_states.next, MDL); while (io) { omapi_object_t *obj; FD_ZERO (&r); FD_ZERO (&w); t0.tv_sec = t0.tv_usec = 0; if (io -> readfd && io -> inner && (desc = (*(io -> readfd)) (io -> inner)) >= 0) { FD_SET (desc, &r); count = select (desc + 1, &r, &w, &x, &t0); bogon: if (count < 0) { log_error ("Bad descriptor %d.", desc); for (obj = (omapi_object_t *)io; obj -> outer; obj = obj -> outer) ; for (; obj; obj = obj -> inner) { omapi_value_t *ov; int len; const char *s; ov = (omapi_value_t *)0; status = omapi_get_value_str (obj, (omapi_object_t *)0, "name", &ov); if(status!=ISC_R_SUCCESS){ log_error("omapi_get_value_str failed!\n"); } if (ov && ov -> value && (ov -> value -> type == omapi_datatype_string)) { s = (char *) ov -> value -> u.buffer.value; len = ov -> value -> u.buffer.len; } else { s = ""; len = 0; } log_error ("Object %lx %s%s%.*s", (unsigned long)obj, obj -> type -> name, len ? " " : "", len, s); if (len) omapi_value_dereference (&ov, MDL); } (*(io -> reaper)) (io -> inner); if (prev) { omapi_io_dereference (&prev -> next, MDL); if (io -> next) omapi_io_reference (&prev -> next, io -> next, MDL); } else { omapi_io_dereference (&omapi_io_states.next, MDL); if (io -> next) omapi_io_reference (&omapi_io_states.next, io -> next, MDL); } omapi_io_dereference (&io, MDL); goto again; } } FD_ZERO (&r); FD_ZERO (&w); t0.tv_sec = t0.tv_usec = 0; /* Same deal for write fdets. */ if (io -> writefd && io -> inner && (desc = (*(io -> writefd)) (io -> inner)) >= 0) { FD_SET (desc, &w); count = select (desc + 1, &r, &w, &x, &t0); if (count < 0) goto bogon; } if (prev) omapi_io_dereference (&prev, MDL); omapi_io_reference (&prev, io, MDL); omapi_io_dereference (&io, MDL); if (prev -> next) omapi_io_reference (&io, prev -> next, MDL); } if (prev) omapi_io_dereference (&prev, MDL); } for (io = omapi_io_states.next; io; io = io -> next) { if (!io -> inner) continue; omapi_object_reference (&tmp, io -> inner, MDL); /* Check for a read descriptor, and if there is one, see if we got input on that socket. */ if (io -> readfd && (desc = (*(io -> readfd)) (tmp)) >= 0) { if (FD_ISSET (desc, &r)) ((*(io -> reader)) (tmp)); } /* Same deal for write descriptors. */ if (io -> writefd && (desc = (*(io -> writefd)) (tmp)) >= 0) { if (FD_ISSET (desc, &w)) ((*(io -> writer)) (tmp)); } omapi_object_dereference (&tmp, MDL); } /* Now check for I/O handles that are no longer valid, and remove them from the list. */ prev = NULL; io = NULL; if (omapi_io_states.next != NULL) { omapi_io_reference(&io, omapi_io_states.next, MDL); } while (io != NULL) { if ((io->inner == NULL) || ((io->reaper != NULL) && ((io->reaper)(io->inner) != ISC_R_SUCCESS))) { omapi_io_object_t *tmp = NULL; /* Save a reference to the next pointer, if there is one. */ if (io->next != NULL) { omapi_io_reference(&tmp, io->next, MDL); omapi_io_dereference(&io->next, MDL); } if (prev != NULL) { omapi_io_dereference(&prev->next, MDL); if (tmp != NULL) omapi_io_reference(&prev->next, tmp, MDL); } else { omapi_io_dereference(&omapi_io_states.next, MDL); if (tmp != NULL) omapi_io_reference (&omapi_io_states.next, tmp, MDL); else omapi_signal_in( (omapi_object_t *) &omapi_io_states, "ready"); } if (tmp != NULL) omapi_io_dereference(&tmp, MDL); } else { if (prev != NULL) { omapi_io_dereference(&prev, MDL); } omapi_io_reference(&prev, io, MDL); } /* * Equivalent to: * io = io->next * But using our reference counting voodoo. */ next = NULL; if (io->next != NULL) { omapi_io_reference(&next, io->next, MDL); } omapi_io_dereference(&io, MDL); if (next != NULL) { omapi_io_reference(&io, next, MDL); omapi_io_dereference(&next, MDL); } } if (prev != NULL) { omapi_io_dereference(&prev, MDL); } return ISC_R_SUCCESS; }
// Trigger storage service in low priority process. void storage_service_trigger(void) { trigger_event(data_storage_event_handle); }
// ------------------------------------------------------------------------ // class to move army on adventure map // ------------------------------------------------------------------------ void t_army_mover::do_movement() { int frame = m_army->get_frame(); int frame_count = m_army->get_frame_count(); t_adv_actor_action_id action = m_army->get_action(); t_uint32 current_time = get_time(); t_uint32 next_time = get_next_time() - get_delay(); t_counted_ptr<t_army_mover> ref = this; t_window_ptr adv_frame = m_window->get_frame(); // temporary reference to prevent the adventure frame // from removing itself if the game is over bool entered_new_square = false; declare_timer( timer_1, "do_movement" ); while ( m_frames > 0 && (!m_is_visible || elapsed_time( current_time, next_time ) >= 0) ) { m_offset += m_delta; m_cell_distance -= m_distance_delta; if (m_cell_distance <= m_crossing_point) { enter_new_square(); } m_army->set_frame_offset( m_offset / m_divisor ); frame++; if (action == k_adv_actor_action_walk && frame == frame_count) frame = 0; if (frame < frame_count) m_army->set_frame( frame ); m_frames--; if (m_is_visible) next_time += get_delay(); } if (m_is_visible) set_next_time( next_time ); // if m_frames is zero, we've hit the center of the cell, or we've // finished a prewalk / walk / postwalk sequence if (m_frames == 0) { if ((action == k_adv_actor_action_postwalk || m_path.size() == 0) && m_distance + m_cell_distance == 0) { finish_path(); return; } if (m_cell_distance == 0) { start_new_square(); entered_new_square = true; trigger_event(); if (m_halted) return; } else { m_cell_distance /= m_divisor; m_crossing_point /= m_divisor; } prepare_move( frame ); } if (entered_new_square) { declare_timer( timer_2, "on_starting_new_square" ); on_starting_new_square(); } }
int API main (int argc, char *argv[], char *envp[]) { initalize_syslog (); struct state state; /* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */ struct event_base *base = event_base_new(); if (!base) { fatal ("could not allocated new event base"); } /* Add three priority levels: * 0 - time saving. Must be done before any other events are handled. * 1 - network synchronization events * 2 - any other events (wake, platform, etc) */ event_base_priority_init (base, MAX_EVENT_PRIORITIES); memset (&state, 0, sizeof (state)); set_conf_defaults (&state.opts); parse_argv (&state.opts, argc, argv); check_conf (&state); load_conf (&state.opts); check_conf (&state); if (!state.opts.sources) add_source_to_conf (&state.opts, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PROXY); state.base = base; state.envp = envp; state.backoff = state.opts.wait_between_tries; /* TODO(wad) move this into setup_time_setter */ /* grab a handle to /dev/rtc for time-setter. */ if (state.opts.should_sync_hwclock && platform->rtc_open(&state.hwclock)) { pinfo ("can't open hwclock fd"); state.opts.should_sync_hwclock = 0; } /* install the SIGCHLD handler for the setter and tlsdate */ if (setup_sigchld_event (&state, 1)) { error ("Failed to setup SIGCHLD event"); goto out; } /* fork off the privileged helper */ info ("spawning time setting helper . . ."); if (setup_time_setter (&state)) { error ("could not fork privileged coprocess"); goto out; } /* release the hwclock now that the time-setter is running. */ if (state.opts.should_sync_hwclock) { platform->rtc_close (&state.hwclock); } /* drop privileges before touching any untrusted data */ drop_privs_to (state.opts.user, state.opts.group); /* register a signal handler to save time at shutdown */ if (state.opts.should_save_disk) { struct event *event = event_new (base, SIGTERM, EV_SIGNAL|EV_PERSIST, action_sigterm, &state); if (!event) fatal ("Failed to create SIGTERM event"); event_priority_set (event, PRI_SAVE); event_add (event, NULL); } if (state.opts.should_dbus && init_dbus (&state)) { error ("Failed to initialize DBus"); goto out; } /* Register the tlsdate event before any listeners could show up. */ state.events[E_TLSDATE] = event_new (base, -1, EV_TIMEOUT, action_run_tlsdate, &state); if (!state.events[E_TLSDATE]) { error ("Failed to create tlsdate event"); goto out; } event_priority_set (state.events[E_TLSDATE], PRI_NET); /* The timeout and fd will be filled in per-call. */ if (setup_tlsdate_status (&state)) { error ("Failed to create tlsdate status event"); goto out; } /* TODO(wad) Could use a timeout on this to catch setter death? */ /* EV_READ is for truncation/EPIPE notification */ state.events[E_SAVE] = event_new (base, state.setter_save_fd, EV_READ|EV_WRITE, action_sync_and_save, &state); if (!state.events[E_SAVE]) { error ("Failed to create sync & save event"); goto out; } event_priority_set (state.events[E_SAVE], PRI_SAVE); /* Start by grabbing the system time. */ state.last_sync_type = SYNC_TYPE_RTC; state.last_time = time (NULL); /* If possible, grab disk time and check the two. */ if (state.opts.should_load_disk) { time_t disk_time = state.last_time; if (!load_disk_timestamp (state.timestamp_path, &disk_time)) { info ("disk timestamp available: yes"); if (!is_sane_time (state.last_time) || state.last_time < disk_time) { state.last_sync_type = SYNC_TYPE_DISK; state.last_time = disk_time; } } else { info ("disk timestamp available: no"); } } if (!is_sane_time (state.last_time)) { state.last_sync_type = SYNC_TYPE_BUILD; state.last_time = RECENT_COMPILE_DATE + 1; } /* Save and announce the initial time source. */ trigger_event (&state, E_SAVE, -1); info ("initial time sync type: %s", sync_type_str (state.last_sync_type)); /* Initialize platform specific loop behavior */ if (platform_init_cros (&state)) { error ("Failed to initialize platform code"); goto out; } if (setup_event_route_up (&state)) { error ("Failed to setup route up monitoring"); goto out; } if (setup_event_timer_sync (&state)) { error ("Failed to setup a timer event"); goto out; } if (setup_event_timer_continuity (&state)) { error ("Failed to setup continuity timer"); goto out; } /* Add a forced sync event to the event list. */ action_kickoff_time_sync (-1, EV_TIMEOUT, &state); info ("Entering dispatch . . ."); event_base_dispatch (base); info ("tlsdated terminating gracefully"); out: return cleanup_main (&state); }
void WindowsXbox360ControllerDevice::update( const unsigned long id ) { Core::Message parameters(5,0,0); HWND foreground = GetForegroundWindow(); if ( this->_window_handle == foreground ) { parameters.add_integral_data(0,id); parameters.add_integral_data(2,this->_id); memcpy(&this->_previous_state,&this->_current_state,sizeof(XINPUT_STATE)); if ( XInputGetState(static_cast<DWORD>(this->_id),&this->_current_state) == ERROR_SUCCESS ) { parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_state.Gamepad.sThumbLX)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_state.Gamepad.sThumbLY)); trigger_event(Core::XBOX360_CONTROLLER_LEFTSTICK_POSITION,parameters); parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_state.Gamepad.sThumbRX)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(this->_current_state.Gamepad.sThumbRY)); trigger_event(Core::XBOX360_CONTROLLER_RIGHTSTICK_POSITION,parameters); if ( this->_previous_state.dwPacketNumber != this->_current_state.dwPacketNumber ) { int difference_left_x = this->_current_state.Gamepad.sThumbLX - this->_previous_state.Gamepad.sThumbLX; int difference_left_y = this->_current_state.Gamepad.sThumbLY - this->_previous_state.Gamepad.sThumbLY; int difference_right_x = this->_current_state.Gamepad.sThumbRX - this->_previous_state.Gamepad.sThumbRX; int difference_right_y = this->_current_state.Gamepad.sThumbRY - this->_previous_state.Gamepad.sThumbRY; if ( abs(difference_left_x) > this->_deadzone || abs(difference_left_y) > this->_deadzone ) { parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_left_x)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_left_y)); trigger_event(Core::XBOX360_CONTROLLER_LEFTSTICK_POSITION_CHANGED,parameters); } if ( abs(difference_right_x) > this->_deadzone || abs(difference_right_y) > this->_deadzone ) { parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_right_x)); parameters.add_integral_data(4,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(difference_right_y)); trigger_event(Core::XBOX360_CONTROLLER_RIGHTSTICK_POSITION_CHANGED,parameters); } int up = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP); int down = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN); int left = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT); int right = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT); int start = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_START) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_START); int back = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK); int left_thumb = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB); int right_thumb = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB); int left_shoulder = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER); int right_shoulder = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER); int a = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_A) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_A); int b = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_B) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_B); int x = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_X) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_X); int y = (this->_current_state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) - (this->_previous_state.Gamepad.wButtons & XINPUT_GAMEPAD_Y); int left_trigger = this->_current_state.Gamepad.bLeftTrigger - this->_previous_state.Gamepad.bLeftTrigger; int right_trigger = this->_current_state.Gamepad.bRightTrigger - this->_previous_state.Gamepad.bRightTrigger; parameters.add_integral_data(3,0); parameters.add_integral_data(4,0); if ( up < 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_UP_UP,parameters); else if ( up > 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_UP_DOWN,parameters); if ( down < 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_DOWN_UP,parameters); else if ( down > 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_DOWN_DOWN,parameters); if ( left < 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_LEFT_UP,parameters); else if ( left > 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_LEFT_DOWN,parameters); if ( right < 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_RIGHT_UP,parameters); else if ( right > 0 ) trigger_event(Core::XBOX360_CONTROLLER_DPAD_RIGHT_DOWN,parameters); if ( start < 0 ) trigger_event(Core::XBOX360_CONTROLLER_START_UP,parameters); else if ( start > 0 ) trigger_event(Core::XBOX360_CONTROLLER_START_DOWN,parameters); if ( back < 0 ) trigger_event(Core::XBOX360_CONTROLLER_BACK_UP,parameters); else if ( back > 0 ) trigger_event(Core::XBOX360_CONTROLLER_BACK_DOWN,parameters); if ( left_thumb < 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTSTICK_UP,parameters); else if ( left_thumb > 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTSTICK_DOWN,parameters); if ( right_thumb < 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTSTICK_UP,parameters); else if ( right_thumb > 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTSTICK_DOWN,parameters); if ( left_shoulder < 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTSHOULDER_UP,parameters); else if ( left_shoulder > 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTSHOULDER_DOWN,parameters); if ( right_shoulder < 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTSHOULDER_UP,parameters); else if ( right_shoulder > 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTSHOULDER_DOWN,parameters); if ( a < 0 ) trigger_event(Core::XBOX360_CONTROLLER_A_UP,parameters); else if ( a > 0 ) trigger_event(Core::XBOX360_CONTROLLER_A_DOWN,parameters); if ( b < 0 ) trigger_event(Core::XBOX360_CONTROLLER_B_UP,parameters); else if ( b > 0 ) trigger_event(Core::XBOX360_CONTROLLER_B_DOWN,parameters); if ( x < 0 ) trigger_event(Core::XBOX360_CONTROLLER_X_UP,parameters); else if ( x > 0 ) trigger_event(Core::XBOX360_CONTROLLER_X_DOWN,parameters); if ( y < 0 ) trigger_event(Core::XBOX360_CONTROLLER_Y_UP,parameters); else if ( y > 0 ) trigger_event(Core::XBOX360_CONTROLLER_Y_DOWN,parameters); parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(left_trigger)); if ( left_trigger < 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTTRIGGER_UP,parameters); else if ( left_trigger > 0 ) trigger_event(Core::XBOX360_CONTROLLER_LEFTTRIGGER_DOWN,parameters); parameters.add_integral_data(3,static_cast<Core::MESSAGE_INTEGRAL_DATA_TYPE>(right_trigger)); if ( right_trigger < 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTTRIGGER_UP,parameters); else if ( right_trigger > 0 ) trigger_event(Core::XBOX360_CONTROLLER_RIGHTTRIGGER_DOWN,parameters); } } } };
/** * Pick up object. * @param pl Object that is picking up the object. * @param op Object to put tmp into. * @param tmp Object to pick up. * @param nrof Number to pick up (0 means all of them). */ static void pick_up_object(object *pl, object *op, object *tmp, int nrof) { char buf[HUGE_BUF]; object *env = tmp->env; int tmp_nrof = tmp->nrof ? tmp->nrof : 1; if (pl->type == PLAYER) { CONTR(pl)->praying = 0; } /* IF the player is flying & trying to take the item out of a container * that is in his inventory, let him. tmp->env points to the container * (sack, luggage, etc), tmp->env->env then points to the player (nested * containers not allowed as of now) */ if (QUERY_FLAG(pl, FLAG_FLYING) && !QUERY_FLAG(pl, FLAG_WIZ) && is_player_inv(tmp) != pl) { new_draw_info(NDI_UNIQUE, pl, "You are levitating, you can't reach the ground!"); return; } if (QUERY_FLAG(tmp, FLAG_WAS_WIZ) && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) { new_draw_info(NDI_UNIQUE, pl, "The object disappears in a puff of smoke!\nIt must have been an illusion."); if (pl->type == PLAYER) { esrv_del_item(CONTR(pl), tmp->count, tmp->env); } if (!QUERY_FLAG(tmp, FLAG_REMOVED)) { remove_ob(tmp); check_walk_off(tmp, NULL, MOVE_APPLY_VANISHED); } return; } if (nrof > tmp_nrof || nrof == 0) { nrof = tmp_nrof; } if (!player_can_carry(pl, tmp, nrof)) { new_draw_info(NDI_UNIQUE, pl, "That item is too heavy for you to pick up."); return; } if (tmp->type == CONTAINER) { container_unlink(NULL, tmp); } /* Trigger the PICKUP event */ if (trigger_event(EVENT_PICKUP, pl, tmp, op, NULL, tmp_nrof, 0, 0, SCRIPT_FIX_ACTIVATOR)) { return; } #ifndef REAL_WIZ if (QUERY_FLAG(pl, FLAG_WAS_WIZ)) { SET_FLAG(tmp, FLAG_WAS_WIZ); } #endif if (QUERY_FLAG(tmp, FLAG_UNPAID)) { /* This is a clone shop - clone an item for inventory */ if (QUERY_FLAG(tmp, FLAG_NO_PICK)) { tmp = object_create_clone(tmp); CLEAR_FLAG(tmp, FLAG_NO_PICK); SET_FLAG(tmp, FLAG_STARTEQUIP); tmp->nrof = nrof; tmp_nrof = nrof; snprintf(buf, sizeof(buf), "You pick up %s for %s from the storage.", query_name(tmp, NULL), query_cost_string(tmp, pl, F_BUY)); } /* This is an unique shop item */ else { tmp->nrof = nrof; snprintf(buf, sizeof(buf), "%s will cost you %s.", query_name(tmp, NULL), query_cost_string(tmp, pl, F_BUY)); tmp->nrof = tmp_nrof; } } else { tmp->nrof = nrof; snprintf(buf, sizeof(buf), "You pick up the %s.", query_name(tmp, NULL)); tmp->nrof = tmp_nrof; } if (nrof != tmp_nrof) { object *tmp2 = tmp, *tmp2_cont = tmp->env; tag_t tmp2_tag = tmp2->count; char err[MAX_BUF]; tmp = get_split_ob(tmp, nrof, err, sizeof(err)); if (!tmp) { new_draw_info(NDI_UNIQUE, pl, err); return; } /* Tell the client what happened to rest of the objects */ if (pl->type == PLAYER) { if (was_destroyed(tmp2, tmp2_tag)) { esrv_del_item(CONTR(pl), tmp2_tag, tmp2_cont); } else { esrv_send_item(pl, tmp2); } } } else { /* If the object is in a container, send a delete to the client. * - we are moving all the items from the container to elsewhere, * so it needs to be deleted. */ if (!QUERY_FLAG(tmp, FLAG_REMOVED)) { if (tmp->env && pl->type == PLAYER) { esrv_del_item (CONTR(pl), tmp->count, tmp->env); } /* Unlink it - no move off check */ remove_ob(tmp); } } new_draw_info(NDI_UNIQUE, pl, buf); tmp = insert_ob_in_ob(tmp, op); /* All the stuff below deals with client/server code, and is only * usable by players */ if (pl->type != PLAYER) { return; } esrv_send_item(pl, tmp); /* These are needed to update the weight for the container we * are putting the object in, and the players weight, if different. */ esrv_update_item(UPD_WEIGHT, pl, op); if (op != pl) { esrv_send_item(pl, pl); } /* Update the container the object was in */ if (env && env != pl && env != op) { esrv_update_item(UPD_WEIGHT, pl, env); } }
// Trigger the I2C1 service routine to run at low priority void I2C1_trigger_service(void) { trigger_event(I2C1_service_handle); }
/** * If the player should die (lack of hp, food, etc), we call this. * * Will remove diseases, apply death penalties, and so on. * @param op The player in jeopardy. */ void kill_player(object *op) { char buf[HUGE_BUF]; int x, y, i; /* this is for resurrection */ mapstruct *map; object *tmp; int z; int num_stats_lose; int lost_a_stat; int lose_this_stat; int this_stat; if (pvp_area(NULL, op)) { new_draw_info(NDI_UNIQUE | NDI_NAVY, op, "You have been defeated in combat!"); new_draw_info(NDI_UNIQUE | NDI_NAVY, op, "Local medics have saved your life..."); /* Restore player */ cast_heal(op, MAXLEVEL, op, SP_CURE_POISON); /* Remove any disease */ cure_disease(op, NULL); op->stats.hp = op->stats.maxhp; if (op->stats.food <= 0) { op->stats.food = 999; } /* Create a bodypart-trophy to make the winner happy */ tmp = arch_to_object(find_archetype("finger")); if (tmp != NULL) { char race[MAX_BUF]; snprintf(buf, sizeof(buf), "%s's finger", op->name); FREE_AND_COPY_HASH(tmp->name, buf); snprintf(buf, sizeof(buf), "This finger has been cut off %s the %s, when %s was defeated at level %d by %s.", op->name, player_get_race_class(op, race, sizeof(race)), gender_subjective[object_get_gender(op)], op->level, CONTR(op)->killer[0] == '\0' ? "something nasty" : CONTR(op)->killer); FREE_AND_COPY_HASH(tmp->msg, buf); tmp->value = 0, tmp->material = 0, tmp->type = 0; tmp->x = op->x, tmp->y = op->y; insert_ob_in_map(tmp, op->map, op, 0); } /* Teleport defeated player to new destination */ transfer_ob(op, MAP_ENTER_X(op->map), MAP_ENTER_Y(op->map), 0, NULL, NULL); return; } if (save_life(op)) { return; } /* Trigger the DEATH event */ if (trigger_event(EVENT_DEATH, NULL, op, NULL, NULL, 0, 0, 0, SCRIPT_FIX_ALL)) { return; } /* Trigger the global GDEATH event */ trigger_global_event(EVENT_GDEATH, NULL, op); play_sound_player_only(CONTR(op), SOUND_PLAYER_DIES, SOUND_NORMAL, 0, 0); /* Save the map location for corpse, gravestone */ x = op->x; y = op->y; map = op->map; /* Basically two ways to go - remove a stat permanently, or just * make it depletion. This bunch of code deals with that aspect * of death. */ if (settings.balanced_stat_loss) { /* If stat loss is permanent, lose one stat only. */ /* Lower level chars don't lose as many stats because they suffer more if they do. */ if (settings.stat_loss_on_death) { num_stats_lose = 1; } else { num_stats_lose = 1 + op->level / BALSL_NUMBER_LOSSES_RATIO; } } else { num_stats_lose = 1; } lost_a_stat = 0; /* Only decrease stats if you are level 3 or higher. */ for (z = 0; z < num_stats_lose; z++) { if (settings.stat_loss_on_death && op->level > 3) { /* Pick a random stat and take a point off it. Tell the * player what he lost. */ i = rndm(1, NUM_STATS) - 1; change_attr_value(&(op->stats), i, -1); check_stat_bounds(&(op->stats)); change_attr_value(&(CONTR(op)->orig_stats), i, -1); check_stat_bounds(&(CONTR(op)->orig_stats)); new_draw_info(NDI_UNIQUE, op, lose_msg[i]); lost_a_stat = 1; } else if (op->level > 3) { /* Deplete a stat */ archetype *deparch = find_archetype("depletion"); object *dep; i = rndm(1, NUM_STATS) - 1; dep = present_arch_in_ob(deparch, op); if (!dep) { dep = arch_to_object(deparch); insert_ob_in_ob(dep, op); } lose_this_stat = 1; if (settings.balanced_stat_loss) { /* Get the stat that we're about to deplete. */ this_stat = get_attr_value(&(dep->stats), i); if (this_stat < 0) { int loss_chance = 1 + op->level / BALSL_LOSS_CHANCE_RATIO; int keep_chance = this_stat * this_stat; /* Yes, I am paranoid. Sue me. */ if (keep_chance < 1) { keep_chance = 1; } /* There is a maximum depletion total per level. */ if (this_stat < -1 - op->level / BALSL_MAX_LOSS_RATIO) { lose_this_stat = 0; } else { /* Take loss chance vs keep chance to see if we retain the stat. */ if (rndm(0, loss_chance + keep_chance - 1) < keep_chance) { lose_this_stat = 0; } } } } if (lose_this_stat) { this_stat = get_attr_value(&(dep->stats), i); /* We could try to do something clever like find another * stat to reduce if this fails. But chances are, if * stats have been depleted to -50, all are pretty low * and should be roughly the same, so it shouldn't make a * difference. */ if (this_stat >= -50) { change_attr_value(&(dep->stats), i, -1); SET_FLAG(dep, FLAG_APPLIED); new_draw_info(NDI_UNIQUE, op, lose_msg[i]); fix_player(op); lost_a_stat = 1; } } } } /* If no stat lost, tell the player. */ if (!lost_a_stat) { const char *god = determine_god(op); if (god && god != shstr_cons.none) { new_draw_info_format(NDI_UNIQUE, op, "For a brief moment you feel the holy presence of %s protecting you.", god); } else { new_draw_info(NDI_UNIQUE, op, "For a brief moment you feel a holy presence protecting you."); } } /* Put a gravestone up where the character 'almost' died. */ tmp = arch_to_object(find_archetype("gravestone")); snprintf(buf, sizeof(buf), "%s's gravestone", op->name); FREE_AND_COPY_HASH(tmp->name, buf); FREE_AND_COPY_HASH(tmp->msg, gravestone_text(op)); tmp->x = op->x, tmp->y = op->y; insert_ob_in_map(tmp, op->map, NULL, 0); /* Subtract the experience points, if we died because of food give us * food, and reset HP... */ /* Remove any poisoning the character may be suffering. */ cast_heal(op, MAXLEVEL, op, SP_CURE_POISON); /* Remove any disease */ cure_disease(op, NULL); /* Apply death experience penalty. */ apply_death_exp_penalty(op); if (op->stats.food < 0) { op->stats.food = 900; } op->stats.hp = op->stats.maxhp; op->stats.sp = op->stats.maxsp; op->stats.grace = op->stats.maxgrace; hiscore_check(op, 1); /* Otherwise the highscore can get entries like 'xxx was killed by pudding * on map Wilderness' even if they were killed in a dungeon. */ CONTR(op)->killer[0] = '\0'; /* Check to see if the player is in a shop. Ii so, then check to see * if the player has any unpaid items. If so, remove them and put * them back in the map. */ tmp = get_map_ob(op->map, op->x, op->y); if (tmp && tmp->type == SHOP_FLOOR) { remove_unpaid_objects(op->inv, op); } /* Move player to his current respawn position (last savebed). */ enter_player_savebed(op); /* Show a nasty message */ new_draw_info(NDI_UNIQUE, op, "YOU HAVE DIED."); save_player(op, 1); return; }