int monster::deal_projectile_attack(Creature *source, double missed_by, const projectile& proj, dealt_damage_instance &dealt_dam) { bool u_see_mon = g->u_see(this); if (has_flag(MF_HARDTOSHOOT) && !one_in(10 - 10 * (.8 - missed_by)) && // Maxes out at 50% chance with perfect hit !proj.wide) { if (u_see_mon) add_msg(_("The shot passes through %s without hitting."), disp_name().c_str()); return 0; } // Not HARDTOSHOOT // if it's a headshot with no head, make it not a headshot if (missed_by < 0.2 && has_flag(MF_NOHEAD)) { missed_by = 0.2; } mdefense mdf; if(!is_hallucination() && source != NULL) { (mdf.*type->sp_defense)(this, &proj); } // whip has a chance to scare wildlife if(proj.proj_effects.count("WHIP") && type->in_category("WILDLIFE") && one_in(3)) { add_effect("run", rng(3, 5)); } return Creature::deal_projectile_attack(source, missed_by, proj, dealt_dam); }
static void handle_notification(void *arg) { struct lmp_endpoint *ep = arg; errval_t err; do { // consume messages struct lmp_recv_msg msg = LMP_RECV_MSG_INIT; err = lmp_endpoint_recv(ep, &msg.buf, NULL); if (err_is_ok(err)) { if(msg.buf.msglen == 1) { domainid_t domid = msg.words[0]; // XXX: This is done by spawnd now if (domid != 0) { debug_printf("Dispatcher with domain ID %"PRIuDOMAINID" exited\n", domid); } } else if(msg.buf.msglen == sizeof(struct RAM) / sizeof(uintptr_t) + 1) { #ifndef __arm__ //defined(__x86_64__) || defined(__i386__) union rammsg { uintptr_t msgwords[LMP_MSG_LENGTH]; struct RAM ram; } *u; u = (union rammsg *)&msg.words; /* printf("%s.%d: RAM cap deleted, base = %" PRIxGENPADDR ", bits = %u\n", */ /* disp_name(), disp_get_core_id(), ram->base, ram->bits); */ err = reclaim_memory(u->ram.base, u->ram.bits); if(err_is_fail(err)) { DEBUG_ERR(err, "reclaim_memory"); } #else /* XXX: Disabling memory reclamation on ARM. I * couldn't get the compiler to accept the above code * due to strict aliasing restrictions. I do believe * though that the above is according to the C99 * spec. Please help fix it, so that it can be * enabled. */ #endif } else { printf("%s: Unknown kernel notification of length %zu received\n", disp_name(), msg.buf.msglen); } } else if (err_no(err) != LIB_ERR_NO_LMP_MSG) { DEBUG_ERR(err, "unexpected error from lmp_endpoint_recv"); } } while(err_is_ok(err)); // re-register struct event_closure cl = { .handler = handle_notification, .arg = arg, }; err = lmp_endpoint_register(ep, get_default_waitset(), cl); assert(err_is_ok(err)); }
void disp_default(Instruction ins, Emulator *emul) { disp_name(ins); printf(" "); disp_regs_and_imm(ins); }
void monster::add_msg_if_npc(game_message_type type, const char *msg, ...) const { va_list ap; va_start(ap, msg); std::string processed_npc_string = vstring_format(msg, ap); processed_npc_string = replace_with_npc_name(processed_npc_string, disp_name()); add_msg(type, processed_npc_string.c_str()); va_end(ap); }
void monster::add_msg_player_or_npc(game_message_type type, const char *, const char* npc_str, ...) const { va_list ap; va_start(ap, npc_str); if (g->u.sees(*this)) { std::string processed_npc_string = vstring_format(npc_str, ap); processed_npc_string = replace_with_npc_name(processed_npc_string, disp_name()); add_msg(type, processed_npc_string.c_str()); } va_end(ap); }
void disp_pop_push(Instruction ins, Emulator *emul) { disp_name(ins); printf(" "); printf("{"); if(ins.reg.size > 0) disp_regs(ins.reg); printf("}"); }
void disp_not_decoded(Instruction ins) { printf("\n"); disp_name(ins); // printf("\n"); // printf(" name_in: %s\tname_out: %s\n", ins.name_in, ins.name_out); // printf(" mask: %8x\topcode: %8x\n", ins.mask, ins.opcode); // printf("\n reg "); // disp_plgtab(ins.reg); // printf("\n imm "); // disp_plgtab(ins.imm); // printf("\n ext "); // disp_plgtab(ins.ext); }
/** * \brief registers the Xeon Phi driver card with the Xeon Phi Manager * * \param svc_iref iref of the own exported Xeon Phi driver interface * \param id returns the assigned Xeon Phi card ID * \param num returns the size of the cards array * \param irefs returns array of irefs to the other cards * * NOTE: this is a blocking function. The function will only return after * the Xeon Phi manager connection has been fully established and the * registration protocol has been executed. * * \returns SYS_ERR_OK on success * errval on failure */ errval_t xeon_phi_manager_client_register(iref_t svc_iref, uint8_t *id, uint8_t *num, iref_t **irefs) { errval_t err, msgerr; if (strcmp(disp_name(), "xeon_phi") != 0) { USER_PANIC("client register called on non xeon phi driver"); return -1; } if (conn_state >= XPM_STATE_REGISTER_OK) { return SYS_ERR_OK; } DEBUG_XPMC("Registration with Xeon Phi Manager service.\n"); err = xpm_bind(); if (err_is_fail(err)) { return err; } xpm_reg_data.svc_iref = svc_iref; xeon_phi_manager_cards_t cards; err = xpm_rpc_client.vtbl.register_driver(&xpm_rpc_client, svc_iref, id, &cards, &msgerr); if (err_is_fail(err)) { return err; } if (err_is_fail(msgerr)) { return msgerr; } conn_state = XPM_STATE_REGISTER_OK; iref_t *cardiref =calloc(cards.num, sizeof(iref_t)); assert(cardiref); for(uint32_t i = 0; i < cards.num; ++i) { cardiref[i] = ((iref_t *)&cards.card0)[i]; } *irefs = cardiref; *num = cards.num; return SYS_ERR_OK; }
int monster::deal_melee_attack(Creature *source, int hitroll, bool crit, const damage_instance& d, dealt_damage_instance &dealt_dam) { if (has_flag(MF_ELECTRIC)) { // shockers electrocute melee attackers if (source != NULL && source->is_player() && !g->u.wearing_something_on(bp_hands) && (g->u.weapon.conductive() || g->u.unarmed_attack()) ) { damage_instance shock; shock.add_damage(DT_ELECTRIC, rng(0,1)); source->deal_damage(this, bp_arms, 1, shock); g->add_msg_if_player(source, _("Contact with %s shocks you!"), disp_name().c_str()); } } return Creature::deal_melee_attack(source, hitroll, crit, d, dealt_dam); }
void Creature::deal_melee_hit(Creature *source, int hit_spread, bool critical_hit, const damage_instance &dam, dealt_damage_instance &dealt_dam) { damage_instance d = dam; // copy, since we will mutate in block_hit body_part bp_hit = select_body_part(source, hit_spread); block_hit(source, bp_hit, d); // Bashing crit if (critical_hit) { int turns_stunned = (d.type_damage(DT_BASH) + hit_spread) / 20; if (turns_stunned > 6) { turns_stunned = 6; } if (turns_stunned > 0) { add_effect("stunned", turns_stunned); } } // Stabbing effects int stab_moves = rng(d.type_damage(DT_STAB) / 2, d.type_damage(DT_STAB) * 1.5); if (critical_hit) { stab_moves *= 1.5; } if (stab_moves >= 150) { if (is_player() && (!g->u.has_trait("LEG_TENT_BRACE") || g->u.footwear_factor() == 1 || (g->u.footwear_factor() == .5 && one_in(2))) ) { // can the player force their self to the ground? probably not. source->add_msg_if_npc( m_bad, _("<npcname> forces you to the ground!")); } else { source->add_msg_player_or_npc( m_good, _("You force %s to the ground!"), _("<npcname> forces %s to the ground!"), disp_name().c_str() ); } if (!g->u.has_trait("LEG_TENT_BRACE") || g->u.footwear_factor() == 1 || (g->u.footwear_factor() == .5 && one_in(2))) { add_effect("downed", 1); mod_moves(-stab_moves / 2); } } else { mod_moves(-stab_moves); } on_gethit(source, bp_hit, d); // trigger on-gethit events dealt_dam = deal_damage(source, bp_hit, d); dealt_dam.bp_hit = bp_hit; }
/** * \brief looks up the symbol by a given index * * \param idx the index of the symbol to look up * \param ret_name returns the name of the symbol * \param ret_addr returns the address of the symbol * * \returns SYS_ERR_OK on success * errval on failure */ errval_t spawn_symval_lookup_idx(uint32_t idx, char **ret_name, genvaddr_t *ret_addr) { if (symvals) { if (symvals[idx].addr != 0) { if (ret_name) { *ret_name = symvals[idx].name; } if (ret_addr) { *ret_addr = symvals[idx].addr; } } } return spawn_symval_lookup(disp_name(), idx, ret_name, ret_addr); }
int monster::deal_projectile_attack(Creature *source, double missed_by, const projectile& proj, dealt_damage_instance &dealt_dam) { bool u_see_mon = g->u_see(this); if (has_flag(MF_HARDTOSHOOT) && !one_in(10 - 10 * (.8 - missed_by)) && // Maxes out at 50% chance with perfect hit !proj.wide) { if (u_see_mon) g->add_msg(_("The shot passes through the %s without hitting."), disp_name().c_str()); return 0; } // Not HARDTOSHOOT // if it's a headshot with no head, make it not a headshot if (missed_by < 0.2 && has_flag(MF_NOHEAD)) { missed_by = 0.2; } return Creature::deal_projectile_attack(source, missed_by, proj, dealt_dam); }
void monster::add_msg_if_npc(game_message_type type, const char *msg, ...) { va_list ap; va_start(ap, msg); std::string processed_npc_string = vstring_format(msg, ap); // These strings contain the substring <npcname>, // if present replace it with the actual monster name. size_t offset = processed_npc_string.find("<npcname>"); if (offset != std::string::npos) { processed_npc_string.replace(offset, 9, disp_name()); if (offset == 0 && !processed_npc_string.empty()) { capitalize_letter(processed_npc_string, 0); } } add_msg(type, processed_npc_string.c_str()); va_end(ap); }
void disp_ldr(Instruction ins, Emulator *emul) { disp_name(ins); printf(" "); disp_reg_name(ins.reg.plages[0]); printf(", ["); disp_reg_name(ins.reg.plages[1]); if(ins.imm.size > 0 && ins.imm.plages->value > 0) { printf(", "); disp_imm(ins.imm); } printf("]"); }
void monster::add_msg_player_or_npc(const char *, const char* npc_str, ...) { va_list ap; va_start(ap, npc_str); if (g->u_see(this)) { std::string processed_npc_string = vstring_format(npc_str, ap); // These strings contain the substring <npcname>, // if present replace it with the actual monster name. size_t offset = processed_npc_string.find("<npcname>"); if (offset != std::string::npos) { processed_npc_string.replace(offset, 9, disp_name()); if (offset == 0 && !processed_npc_string.empty()) { capitalize_letter(processed_npc_string, 0); } } add_msg(processed_npc_string.c_str()); } va_end(ap); }
void disp_sub_sp(Instruction ins, Emulator *emul) { disp_name(ins); printf(" "); if(ins.reg.size > 0) disp_regs(ins.reg); else printf("sp"); printf(", sp"); if(ins.imm.size > 0) { printf(", "); disp_imm(ins.imm); } }
void Creature::deal_melee_hit( Creature *source, int hit_spread, bool critical_hit, const damage_instance &dam, dealt_damage_instance &dealt_dam ) { damage_instance d = dam; // copy, since we will mutate in block_hit body_part bp_hit = select_body_part(source, hit_spread); block_hit(source, bp_hit, d); // Bashing critical if( critical_hit && !is_immune_effect( effect_stunned ) ) { if( d.type_damage(DT_BASH) * hit_spread > get_hp_max() ) { add_effect( effect_stunned, 1_turns ); // 1 turn is enough } } // Stabbing effects int stab_moves = rng( d.type_damage(DT_STAB) / 2, d.type_damage(DT_STAB) * 1.5 ); if (critical_hit) { stab_moves *= 1.5; } if( stab_moves >= 150 && !is_immune_effect( effect_downed ) ) { if( is_player() ) { source->add_msg_if_npc( m_bad, _("<npcname> forces you to the ground!")); } else { source->add_msg_player_or_npc( m_good, _("You force %s to the ground!"), _("<npcname> forces %s to the ground!"), disp_name().c_str() ); } add_effect( effect_downed, 1_turns ); mod_moves(-stab_moves / 2); } else { mod_moves(-stab_moves); } on_hit( source, bp_hit ); // trigger on-gethit events dealt_dam = deal_damage(source, bp_hit, d); dealt_dam.bp_hit = bp_hit; }
int monster::deal_projectile_attack(Creature *source, double missed_by, const projectile& proj, dealt_damage_instance &dealt_dam) { bool u_see_mon = g->u_see(this); if (has_flag(MF_HARDTOSHOOT) && !one_in(10 - 10 * (.8 - missed_by)) && // Maxes out at 50% chance with perfect hit !proj.wide) { if (u_see_mon) Messages::player_messages.add_msg(_("The shot passes through %s without hitting."), disp_name().c_str()); return 0; } // Not HARDTOSHOOT // if it's a headshot with no head, make it not a headshot if (missed_by < 0.2 && has_flag(MF_NOHEAD)) { missed_by = 0.2; } mdefense mdf; if(!is_hallucination() && source != NULL) { (mdf.*type->sp_defense)(this, &proj); } return Creature::deal_projectile_attack(source, missed_by, proj, dealt_dam); }
void monster::melee_attack(Creature &target, bool, matec_id) { mod_moves(-100); if (type->melee_dice == 0) { // We don't attack, so just return return; } add_effect("hit_by_player", 3); // Make us a valid target for a few turns if (has_flag(MF_HIT_AND_RUN)) { add_effect("run", 4); } bool u_see_me = g->u_see(this); body_part bp_hit; //int highest_hit = 0; int hitstat = type->melee_skill; int hitroll = dice(hitstat,10); damage_instance damage; if(!is_hallucination()) { if (type->melee_dice > 0) { damage.add_damage(DT_BASH, dice(type->melee_dice,type->melee_sides)); } if (type->melee_cut > 0) { damage.add_damage(DT_CUT, type->melee_cut); } } /* TODO: height-related bodypart selection //If the player is knocked down or the monster can fly, any body part is a valid target if(target.is_on_ground() || has_flag(MF_FLIES)){ highest_hit = 20; } else { switch (type->size) { case MS_TINY: highest_hit = 3; break; case MS_SMALL: highest_hit = 12; break; case MS_MEDIUM: highest_hit = 20; break; case MS_LARGE: highest_hit = 28; break; case MS_HUGE: highest_hit = 35; break; } if (digging()){ highest_hit -= 8; } if (highest_hit <= 1){ highest_hit = 2; } } if (highest_hit > 20){ highest_hit = 20; } int bp_rand = rng(0, highest_hit - 1); if (bp_rand <= 2){ bp_hit = bp_legs; } else if (bp_rand <= 10){ bp_hit = bp_torso; } else if (bp_rand <= 14){ bp_hit = bp_arms; } else if (bp_rand <= 16){ bp_hit = bp_mouth; } else if (bp_rand == 18){ bp_hit = bp_eyes; } else{ bp_hit = bp_head; } */ dealt_damage_instance dealt_dam; int hitspread = target.deal_melee_attack(this, hitroll); if (hitspread >= 0) { target.deal_melee_hit(this, hitspread, false, damage, dealt_dam); } bp_hit = dealt_dam.bp_hit; if (hitspread < 0) { // a miss // TODO: characters practice dodge when a hit misses 'em if (target.is_player()) { if (u_see_me) { add_msg(_("You dodge %1$s."), disp_name().c_str()); } else { add_msg(_("You dodge an attack from an unseen source.")); } } else { if (u_see_me) { add_msg(_("The %1$s dodges %2$s attack."), name().c_str(), target.disp_name(true).c_str()); } } //Hallucinations always produce messages but never actually deal damage } else if (is_hallucination() || dealt_dam.total_damage() > 0) { if (target.is_player()) { if (u_see_me) { add_msg(m_bad, _("The %1$s hits your %2$s."), name().c_str(), body_part_name(bp_hit, random_side(bp_hit)).c_str()); } else { add_msg(m_bad, _("Something hits your %s."), body_part_name(bp_hit, random_side(bp_hit)).c_str()); } } else { if (u_see_me) { add_msg(_("The %1$s hits %2$s %3$s."), name().c_str(), target.disp_name(true).c_str(), body_part_name(bp_hit, random_side(bp_hit)).c_str()); } } } else { if (target.is_player()) { if (u_see_me) { add_msg(_("The %1$s hits your %2$s, but your %3$s protects you."), name().c_str(), body_part_name(bp_hit, random_side(bp_hit)).c_str(), target.skin_name().c_str()); } else { add_msg(_("Something hits your %1$s, but your %2$s protects you."), body_part_name(bp_hit, random_side(bp_hit)).c_str(), target.skin_name().c_str()); } } else { if (u_see_me) { add_msg(_("The %1$s hits %2$s %3$s but is stopped by %2$s %4$s."), name().c_str(), target.disp_name(true).c_str(), body_part_name(bp_hit, random_side(bp_hit)).c_str(), target.skin_name().c_str()); } } } if (is_hallucination()) { if(one_in(7)) { dead = true; } return; } // Adjust anger/morale of same-species monsters, if appropriate int anger_adjust = 0, morale_adjust = 0; if (type->has_anger_trigger(MTRIG_FRIEND_ATTACKED)){ anger_adjust += 15; } if (type->has_fear_trigger(MTRIG_FRIEND_ATTACKED)){ morale_adjust -= 15; } if (type->has_placate_trigger(MTRIG_FRIEND_ATTACKED)){ anger_adjust -= 15; } if (anger_adjust != 0 && morale_adjust != 0) { for (int i = 0; i < g->num_zombies(); i++) { g->zombie(i).morale += morale_adjust; g->zombie(i).anger += anger_adjust; } } }
/** * Perform Sanity check of user-configurable values, and initialize all modules. * * \param card_name Name of service implementing ethernet driver * \param queueid Queueid which is allocated to this application * \param opt_waitset Optional pointer to waitset to be used by LWIP * \param opt_mutex Optional pointer to mutex to protect multi-threaded domains * * \returns True iff init completes */ bool lwip_init_ex(const char *card_name, uint64_t queueid, struct waitset *opt_waitset, struct thread_mutex *opt_mutex) { printf("lwip_init_ex: starting......................\n"); DEBUGPRINTPS("LWIP_other: Inside lwip_init\n"); static bool run_once; if (run_once) { return false; } run_once = true; if (opt_waitset == NULL) { printf("#### %s Going ahead with default wait-set\n", disp_name()); lwip_waitset = get_default_waitset(); } else { printf("#### %s Going ahead with non-default wait-set\n", disp_name()); // lwip_waitset = get_default_waitset(); lwip_waitset = opt_waitset; } if (opt_mutex != NULL) { lwip_mutex = opt_mutex; } /* Sanity check user-configurable values */ lwip_sanity_check(); DEBUGPRINTPS("LWIP: lwip_init: done with sanity check\n"); printf("LWIP: done with sanity check\n"); /* Modules initialization */ char port_manager_name[MAX_NET_SERVICE_NAME_LEN]; snprintf(port_manager_name, sizeof(port_manager_name), "%s%s", card_name, NET_PORTS_MNG_SUFFIX); // Connecting to the port_manager_service idc_connect_port_manager_service(port_manager_name); if (is_ctl != 1) { // connecting to ARP lookup service // Doing this before everything else so that we know all needed // services are up and running. char ARP_service_name[MAX_NET_SERVICE_NAME_LEN]; snprintf(ARP_service_name, sizeof(ARP_service_name), "%s%s", card_name, NET_ARP_LOOKUP_SUFFIX); idc_connect_ARP_lookup_service(ARP_service_name); } DEBUGPRINTPS("LWIP: lwip_init: done with connection setup\n"); printf("LWIP: done with connection setup\n"); remaining_lwip_initialization((char *) card_name, queueid); if (is_ctl != 1) { DEBUGPRINTPS("getting IP from ARP service\n"); printf("LWIP: getting IP from ARP service\n"); idc_get_ip_from_ARP_lookup(); } // Register timers... (TCP only) // FIXME: These timers should be added only when first TCP connection // is requested and not when networking is started!!!! static struct periodic_event tcp_timer; errval_t err = periodic_event_create(&tcp_timer, lwip_waitset, TCP_TMR_INTERVAL * 1000, MKCLOSURE((void (*)(void *)) call_tcp_tmr, NULL)); assert(err_is_ok(err)); // FIXME: I am not sure if this should be in the codepath for both // is_ctl and non-is_ctl. Specially becasuse non is_ctl is anyways // adding one interface with idc_get_ip* call. // Bring interface up struct ip_addr ipaddr, netmask, gw; ip_addr_set(&ipaddr, IP_ADDR_ANY); ip_addr_set(&netmask, IP_ADDR_ANY); ip_addr_set(&gw, IP_ADDR_ANY); struct netif *n = netif_add(&netif, &ipaddr, &netmask, &gw, NULL, bfeth_init, ethernet_input); assert(n != NULL); extern bool lwip_init_done; lwip_init_done = true; printf("lwip_init_ex: done......................\n"); return true; }
static void remaining_lwip_initialization(char *card_name, uint64_t queueid) { nb = netbench_alloc("app", RECORDED_EVENTS_COUNT); //asq: connect to the NIC driver, before doing anything else idc_connect_to_driver(card_name, queueid); DEBUGPRINTPS("Connected to driver [%s]\n", card_name); stats_init(); sys_init(); DEBUGPRINTPS("remaining_lwip_init: allocating pbuf memory\n"); #ifdef CONFIG_QEMU_NETWORK printf("#### Networking with small amount of memory #####\n"); #endif // CONFIG_QEMU_NETWORK printf("#### [%u:%"PRIuDOMAINID":%s] [%s] [%d] MEM_SIZE[%d], " "PBUF_POOL_SIZE[%d], MEMP_MAX[%d], RECEIVE_BUFFERS[%d] qid[%"PRIu64"]####\n", disp_get_core_id(), disp_get_domain_id(), disp_name(), MEM_CONF_LOC, is_ctl, MEM_SIZE, PBUF_POOL_SIZE, MEMP_MAX, RECEIVE_BUFFERS, queueid); memp_init(); // 0'st buffer DEBUGPRINTPS("remaining_lwip_init: allocating memory for sending\n"); mem_init(); // 1'th buffer DEBUGPRINTPS("remaining_lwip_init: done with memroy allocation\n"); DEBUGPRINTPS("LWIP: lwip_starting\n"); netif_init(); #if LWIP_SOCKET lwip_socket_init(); #endif /* LWIP_SOCKET */ ip_init(); DEBUGPRINTPS("r_lwip_init: done ip_init\n"); #if LWIP_ARP etharp_init(); #endif /* LWIP_ARP */ #if LWIP_RAW raw_init(); #endif /* LWIP_RAW */ #if LWIP_UDP udp_init(); DEBUGPRINTPS("r_lwip_init: done udp_init\n"); #endif /* LWIP_UDP */ #if LWIP_TCP tcp_init(); DEBUGPRINTPS("r_lwip_init: done tcp_init\n"); #endif /* LWIP_TCP */ #if LWIP_SNMP snmp_init(); DEBUGPRINTPS("r_lwip_init: done snmp_init\n"); #endif /* LWIP_SNMP */ #if LWIP_AUTOIP autoip_init(); DEBUGPRINTPS("r_lwip_init: done autoip_init\n"); #endif /* LWIP_AUTOIP */ #if LWIP_IGMP igmp_init(); DEBUGPRINTPS("r_lwip_init: done igmp_init\n"); #endif /* LWIP_IGMP */ DEBUGPRINTPS("r_lwip_init: done2 igmp_init\n"); #if LWIP_DNS DEBUGPRINTPS("r_lwip_init: starting DNS_init\n"); dns_init(); DEBUGPRINTPS("r_lwip_init: done DNS_init\n"); #endif /* LWIP_DNS */ DEBUGPRINTPS("LWIP: lwip_started\n"); }
void monster::melee_attack(Creature &target, bool, matec_id) { mod_moves(-100); if (type->melee_dice == 0) { // We don't attack, so just return return; } add_effect("hit_by_player", 3); // Make us a valid target for a few turns if (has_flag(MF_HIT_AND_RUN)) { add_effect("run", 4); } bool u_see_me = g->u_see(this); body_part bp_hit; //int highest_hit = 0; damage_instance damage; if(!is_hallucination()) { if (type->melee_dice > 0) { damage.add_damage(DT_BASH, dice(type->melee_dice,type->melee_sides)); } if (type->melee_cut > 0) { damage.add_damage(DT_CUT, type->melee_cut); } } dealt_damage_instance dealt_dam; int hitspread = target.deal_melee_attack(this, hit_roll()); if (hitspread >= 0) { target.deal_melee_hit(this, hitspread, false, damage, dealt_dam); } bp_hit = dealt_dam.bp_hit; if (hitspread < 0) { // a miss // TODO: characters practice dodge when a hit misses 'em if (target.is_player()) { if (u_see_me) { add_msg(_("You dodge %s."), disp_name().c_str()); } else { add_msg(_("You dodge an attack from an unseen source.")); } } else { if (u_see_me) { add_msg(_("The %1$s dodges %2$s attack."), name().c_str(), target.disp_name(true).c_str()); } } //Hallucinations always produce messages but never actually deal damage } else if (is_hallucination() || dealt_dam.total_damage() > 0) { if (target.is_player()) { if (u_see_me) { //~ 1$s is attacker name, 2$s is bodypart name in accusative. add_msg(m_bad, _("The %1$s hits your %2$s."), name().c_str(), body_part_name_accusative(bp_hit).c_str()); } else { //~ %s is bodypart name in accusative. add_msg(m_bad, _("Something hits your %s."), body_part_name_accusative(bp_hit).c_str()); } } else { if (u_see_me) { //~ 1$s is attacker name, 2$s is target name, 3$s is bodypart name in accusative. add_msg(_("The %1$s hits %2$s %3$s."), name().c_str(), target.disp_name(true).c_str(), body_part_name_accusative(bp_hit).c_str()); } } } else { if (target.is_player()) { if (u_see_me) { //~ 1$s is attacker name, 2$s is bodypart name in accusative, 3$s is armor name add_msg(_("The %1$s hits your %2$s, but your %3$s protects you."), name().c_str(), body_part_name_accusative(bp_hit).c_str(), target.skin_name().c_str()); } else { //~ 1$s is bodypart name in accusative, 2$s is armor name. add_msg(_("Something hits your %1$s, but your %2$s protects you."), body_part_name_accusative(bp_hit).c_str(), target.skin_name().c_str()); } } else { if (u_see_me) { //~ $1s is monster name, %2$s is that monster target name, //~ $3s is target bodypart name in accusative, 4$s is target armor name. add_msg(_("The %1$s hits %2$s %3$s but is stopped by %2$s %4$s."), name().c_str(), target.disp_name(true).c_str(), body_part_name_accusative(bp_hit).c_str(), target.skin_name().c_str()); } } } if (is_hallucination()) { if(one_in(7)) { die( nullptr ); } return; } // Adjust anger/morale of same-species monsters, if appropriate int anger_adjust = 0, morale_adjust = 0; if (type->has_anger_trigger(MTRIG_FRIEND_ATTACKED)){ anger_adjust += 15; } if (type->has_fear_trigger(MTRIG_FRIEND_ATTACKED)){ morale_adjust -= 15; } if (type->has_placate_trigger(MTRIG_FRIEND_ATTACKED)){ anger_adjust -= 15; } if (anger_adjust != 0 && morale_adjust != 0) { for (size_t i = 0; i < g->num_zombies(); i++) { g->zombie(i).morale += morale_adjust; g->zombie(i).anger += anger_adjust; } } }
std::string Creature::replace_with_npc_name( std::string input ) const { replace_substring( input, "<npcname>", disp_name(), true ); return input; }
int Creature::deal_projectile_attack(Creature *source, double missed_by, const projectile &proj, dealt_damage_instance &dealt_dam) { bool u_see_this = g->u_see(this); body_part bp_hit; int side = rng(0, 1); // do 10,speed because speed could potentially be > 10000 if (dodge_roll() >= dice(10, proj.speed)) { if (is_player()) g->add_msg(_("You dodge %s's projectile!"), skin_name().c_str()); else if (u_see_this) g->add_msg(_("%s dodges %s's projectile."), disp_name().c_str(), source->disp_name().c_str()); return 0; } double hit_value = missed_by + rng_float(-0.5, 0.5); // headshots considered elsewhere if (hit_value <= 0.4) { bp_hit = bp_torso; } else if (one_in(4)) { bp_hit = bp_legs; } else { bp_hit = bp_arms; } double monster_speed_penalty = std::max(double(get_speed()) / 80., 1.0); double goodhit = missed_by / monster_speed_penalty; double damage_mult = 1.0; if (goodhit <= .1) { g->add_msg_if_player(source, _("Headshot!")); damage_mult *= rng_float(5, 8); bp_hit = bp_head; // headshot hits the head, of course } else if (goodhit <= .2) { g->add_msg_if_player(source, _("Critical!")); damage_mult *= rng_float(2, 3); } else if (goodhit <= .4) { g->add_msg_if_player(source, _("Good hit!")); damage_mult *= rng_float(1, 2); } else if (goodhit <= .6) { damage_mult *= rng_float(0.5, 1); } else if (goodhit <= .8) { g->add_msg_if_player(source, _("Grazing hit.")); damage_mult *= rng_float(0, 1); } else { damage_mult *= 0; } // copy it, since we're mutating damage_instance impact = proj.impact; impact.mult_damage(damage_mult); dealt_dam = deal_damage(source, bp_hit, side, impact); dealt_dam.bp_hit = bp_hit; if(u_see_this) { if (damage_mult == 0) { if(source != NULL) { g->add_msg(source->is_player() ? _("You miss!") : _("The shot misses!")); } } else if (dealt_dam.total_damage() == 0) { g->add_msg(_("The shot reflects off the %s!"), skin_name().c_str()); } else if (source != NULL) { if (source->is_player()) { g->add_msg(_("You hit the %s for %d damage."), disp_name().c_str(), dealt_dam.total_damage()); } else if (u_see_this) { g->add_msg(_("%s shoots %s."), source->disp_name().c_str(), disp_name().c_str()); } } } return 0; }
int Creature::deal_melee_attack(Creature *source, int hitroll, bool critical_hit, const damage_instance &dam, dealt_damage_instance &dealt_dam) { int dodgeroll = dodge_roll(); int hit_spread = hitroll - dodgeroll; bool missed = hit_spread <= 0; damage_instance d = dam; // copy, since we will mutate in block_hit if (missed) { return hit_spread; } //bool critical_hit = hit_spread > 30; //scored_crit(dodgeroll); body_part bp_hit; int side = rng(0, 1); int hit_value = hit_spread + dice(10, 6) - 35; if (hit_value >= 40) { bp_hit = bp_eyes; } else if (hit_value >= 30) { bp_hit = bp_head; } else if (hit_value >= 5) { bp_hit = bp_torso; } else if (one_in(4)) { bp_hit = bp_legs; } else { bp_hit = bp_arms; } // Bashing crit if (critical_hit) { int turns_stunned = (d.type_damage(DT_BASH) + hit_spread) / 20; if (turns_stunned > 6) { turns_stunned = 6; } if (turns_stunned > 0) { add_effect("stunned", turns_stunned); } } // Stabbing effects int stab_moves = rng(d.type_damage(DT_STAB) / 2, d.type_damage(DT_STAB) * 1.5); if (critical_hit) { stab_moves *= 1.5; } if (stab_moves >= 150) { if (is_player()) { // can the player force their self to the ground? probably not. g->add_msg_if_npc(source, _("<npcname> forces you to the ground!")); } else { g->add_msg_player_or_npc(source, _("You force %s to the ground!"), _("<npcname> forces %s to the ground!"), disp_name().c_str() ); } add_effect("downed", 1); mod_moves(-stab_moves / 2); } else { mod_moves(-stab_moves); } block_hit(bp_hit, side, d); on_gethit(source, bp_hit, d); // trigger on-gethit events dealt_dam = deal_damage(source, bp_hit, side, d); dealt_dam.bp_hit = bp_hit; /* TODO: add grabs n shit back in if (allow_special && technique.grabs) { // TODO: make this depend on skill (through grab_resist stat) again if (t.get_grab_resist() > 0 && dice(t.get_dex() , 12) > dice(get_dex(), 10)) { g->add_msg_player_or_npc(&t, _("You break the grab!"), _("<npcname> breaks the grab!")); } else if (!unarmed_attack()) { // Move our weapon to a temp slot, if it's not unarmed item tmpweap = remove_weapon(); melee_attack(t, false); // False means a second grab isn't allowed weapon = tmpweap; } else melee_attack(t, false); // False means a second grab isn't allowed } */ return hit_spread; }
hp_part Character::body_window( bool precise ) const { return body_window( disp_name(), true, precise, 0, 0, 0, 0, 0, 0 ); }
// FIXME: why is this not in soft filter management? bool copy_packet_to_user(struct buffer_descriptor *buffer, void *data, uint64_t len, uint64_t flags) { // Must only be called if we use software filtering assert(use_sf); assert(len > 0); assert(data != NULL); assert(buffer != NULL); struct net_queue_manager_binding *b = buffer->con; assert(b != NULL); struct client_closure *cl = (struct client_closure *) b->st; assert(cl != NULL); // check if there are slots which can be used in app (!isempty) if(buffer->rxq.buffer_state_used == 0) { printf("[%s] Dropping packet as no space in userspace " "2cp pkt buf [%" PRIu64 "]: " "size[%zu] used[%zu], after [%"PRIu64"] sent" " added [%"PRIu64"] \n", disp_name(), buffer->buffer_id, buffer->rxq.buffer_state_size, buffer->rxq.buffer_state_used, sent_packets, rx_added); if (cl->debug_state == 4) { ++cl->in_dropped_app_buf_full; } //abort(); // optional, should be removed return false; } if (!is_enough_space_in_queue(cl->q)) { printf("[%s] Dropping packet as app [%d] is not processing packets" "fast enough. Cont queue is almost full [%d], pkt count [%"PRIu64"]\n", disp_name(), cl->cl_no, queue_free_slots(cl->q), sent_packets); if (cl->debug_state == 4) { ++cl->in_dropped_app_buf_full; } // abort(); // FIXME: temparary halt to simplify debugging return false; } // pop the latest buffer from head of queue (this is stack) --buffer->rxq.buffer_state_head; struct buffer_state_metadata *bsm = buffer->rxq.buffer_state + buffer->rxq.buffer_state_head; assert(bsm != NULL); uint64_t offset = bsm->offset; --buffer->rxq.buffer_state_used; assert(offset < buffer->bytes); void *dst = (void *) (uintptr_t) buffer->va + offset; ETHERSRV_DEBUG("Copy packet pos %p %p %p\n", buffer->va, dst, (buffer->va + buffer->bytes)); uint64_t ts = rdtsc(); memcpy_fast((void *) (uintptr_t)dst, data, len); if (cl->debug_state == 4) { netbench_record_event_simple(bm, RE_COPY, ts); } ++sent_packets; // FIXME: remove this! // add trace pkt cpy #if TRACE_ETHERSRV_MODE uint32_t pkt_location = (uint32_t) ((uintptr_t) data); trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_NI_PKT_CPY, pkt_location); #endif // TRACE_ETHERSRV_MODE // Handle raw interface errval_t err = send_raw_xmit_done(b, offset, len, 0, flags); if (err_is_ok(err)) { return true; } else { // As application is not able to process the packet // we will drop this one USER_PANIC("send_raw_xmit_done failed as queue full, can't go further: 2\n"); // FIXME: Don't crash. ignore the packet, undo any changes done by it // and continue. Ideally this shouldn't happen as we are checking for // free space before actually sending the packt. return false; } return true; } // end function: copy_packet_to_user
/** * Attempts to harm a creature with a projectile. * * @param source Pointer to the creature who shot the projectile. * @param attack A structure describing the attack and its results. */ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack &attack ) { const double missed_by = attack.missed_by; if( missed_by >= 1.0 ) { // Total miss return; } const projectile &proj = attack.proj; dealt_damage_instance &dealt_dam = attack.dealt_dam; const auto &proj_effects = proj.proj_effects; const bool u_see_this = g->u.sees(*this); const int avoid_roll = dodge_roll(); // Do dice(10, speed) instead of dice(speed, 10) because speed could potentially be > 10000 const int diff_roll = dice( 10, proj.speed ); // Partial dodge, capped at [0.0, 1.0], added to missed_by const double dodge_rescaled = avoid_roll / static_cast<double>( diff_roll ); const double goodhit = missed_by + std::max( 0.0, std::min( 1.0, dodge_rescaled ) ) ; if( goodhit >= 1.0 ) { // "Avoid" rather than "dodge", because it includes removing self from the line of fire // rather than just Matrix-style bullet dodging if( source != nullptr && g->u.sees( *source ) ) { add_msg_player_or_npc( m_warning, _("You avoid %s projectile!"), _("<npcname> avoids %s projectile."), source->disp_name(true).c_str() ); } else { add_msg_player_or_npc( m_warning, _("You avoid an incoming projectile!"), _("<npcname> avoids an incoming projectile.") ); } attack.missed_by = 1.0; // Arbitrary value return; } // Bounce applies whether it does damage or not. if( proj.proj_effects.count( "BOUNCE" ) ) { add_effect( effect_bounced, 1_turns ); } body_part bp_hit; double hit_value = missed_by + rng_float(-0.5, 0.5); // Headshots considered elsewhere if( hit_value <= 0.4 ) { bp_hit = bp_torso; } else if (one_in(4)) { if( one_in(2)) { bp_hit = bp_leg_l; } else { bp_hit = bp_leg_r; } } else { if( one_in(2)) { bp_hit = bp_arm_l; } else { bp_hit = bp_arm_r; } } double damage_mult = 1.0; std::string message = ""; game_message_type gmtSCTcolor = m_neutral; if( goodhit < accuracy_headshot ) { message = _("Headshot!"); gmtSCTcolor = m_headshot; damage_mult *= rng_float(1.95, 2.05); bp_hit = bp_head; // headshot hits the head, of course } else if( goodhit < accuracy_critical ) { message = _("Critical!"); gmtSCTcolor = m_critical; damage_mult *= rng_float(1.5, 2.0); } else if( goodhit < accuracy_goodhit ) { message = _("Good hit!"); gmtSCTcolor = m_good; damage_mult *= rng_float(1, 1.5); } else if( goodhit < accuracy_standard ) { damage_mult *= rng_float(0.5, 1); } else if( goodhit < accuracy_grazing ) { message = _("Grazing hit."); gmtSCTcolor = m_grazing; damage_mult *= rng_float(0, .25); } if( source != nullptr && !message.empty() ) { source->add_msg_if_player(m_good, message.c_str()); } attack.missed_by = goodhit; // copy it, since we're mutating damage_instance impact = proj.impact; if( damage_mult > 0.0f && proj_effects.count( "NO_DAMAGE_SCALING" ) ) { damage_mult = 1.0f; } impact.mult_damage(damage_mult); if( proj_effects.count( "NOGIB" ) > 0 ) { float dmg_ratio = (float)impact.total_damage() / get_hp_max( player::bp_to_hp( bp_hit ) ); if( dmg_ratio > 1.25f ) { impact.mult_damage( 1.0f / dmg_ratio ); } } dealt_dam = deal_damage(source, bp_hit, impact); dealt_dam.bp_hit = bp_hit; // Apply ammo effects to target. if (proj.proj_effects.count("FLAME")) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, rng( 8_turns, 20_turns ), bp_hit ); } else if (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) { add_effect( effect_onfire, rng( 5_turns, 10_turns ), bp_hit ); } } else if (proj.proj_effects.count("INCENDIARY") ) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, rng( 2_turns, 6_turns ), bp_hit ); } else if ( (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) && one_in(4) ) { add_effect( effect_onfire, rng( 1_turns, 4_turns ), bp_hit ); } } else if (proj.proj_effects.count("IGNITE")) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, 6_turns, bp_hit ); } else if (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) { add_effect( effect_onfire, 10_turns, bp_hit ); } } if( bp_hit == bp_head && proj_effects.count( "BLINDS_EYES" ) ) { // TODO: Change this to require bp_eyes add_env_effect( effect_blind, bp_eyes, 5, rng( 3_turns, 10_turns ) ); } if( proj_effects.count( "APPLY_SAP" ) ) { add_effect( effect_sap, 1_turns * dealt_dam.total_damage() ); } int stun_strength = 0; if (proj.proj_effects.count("BEANBAG")) { stun_strength = 4; } if (proj.proj_effects.count("LARGE_BEANBAG")) { stun_strength = 16; } if( stun_strength > 0 ) { switch( get_size() ) { case MS_TINY: stun_strength *= 4; break; case MS_SMALL: stun_strength *= 2; break; case MS_MEDIUM: default: break; case MS_LARGE: stun_strength /= 2; break; case MS_HUGE: stun_strength /= 4; break; } add_effect( effect_stunned, 1_turns * rng( stun_strength / 2, stun_strength ) ); } if(u_see_this) { if( damage_mult == 0 ) { if( source != nullptr ) { add_msg( source->is_player() ? _("You miss!") : _("The shot misses!") ); } } else if( dealt_dam.total_damage() == 0 ) { //~ 1$ - monster name, 2$ - character's bodypart or monster's skin/armor add_msg( _("The shot reflects off %1$s %2$s!"), disp_name(true).c_str(), is_monster() ? skin_name().c_str() : body_part_name_accusative(bp_hit).c_str() ); } else if( is_player() ) { //monster hits player ranged //~ Hit message. 1$s is bodypart name in accusative. 2$d is damage value. add_msg_if_player(m_bad, _( "You were hit in the %1$s for %2$d damage." ), body_part_name_accusative(bp_hit).c_str(), dealt_dam.total_damage()); } else if( source != nullptr ) { if( source->is_player() ) { //player hits monster ranged SCT.add(posx(), posy(), direction_from(0, 0, posx() - source->posx(), posy() - source->posy()), get_hp_bar(dealt_dam.total_damage(), get_hp_max(), true).first, m_good, message, gmtSCTcolor); if (get_hp() > 0) { SCT.add(posx(), posy(), direction_from(0, 0, posx() - source->posx(), posy() - source->posy()), get_hp_bar(get_hp(), get_hp_max(), true).first, m_good, //~ "hit points", used in scrolling combat text _("hp"), m_neutral, "hp"); } else { SCT.removeCreatureHP(); } add_msg(m_good, _("You hit %s for %d damage."), disp_name().c_str(), dealt_dam.total_damage()); } else if( u_see_this ) { //~ 1$ - shooter, 2$ - target add_msg(_("%1$s shoots %2$s."), source->disp_name().c_str(), disp_name().c_str()); } } } check_dead_state(); attack.hit_critter = this; attack.missed_by = goodhit; }
/***************************************************************** * Interface related: raw interface ****************************************************************/ static void raw_add_buffer(struct net_queue_manager_binding *cc, uint64_t offset, uint64_t length, uint64_t more, uint64_t flags) { struct client_closure *cl = (struct client_closure *) cc->st; struct buffer_descriptor *buffer = cl->buffer_ptr; errval_t err; uint64_t paddr; void *vaddr, *opaque; paddr = ((uint64_t)(uintptr_t) buffer->pa) + offset; vaddr = (void*) ((uintptr_t) buffer->va + (size_t)offset); if (buffer->role == TX_BUFFER_ID) { // Make sure that there is opaque slot available (isfull) assert(buffer->txq.buffer_state_used < (buffer->txq.buffer_state_size - 1)); // Save state for handle_tx_done()/handle_receive_packet struct buffer_state_metadata *bsm = buffer->txq.buffer_state + buffer->txq.buffer_state_head; buffer->txq.buffer_state_head = (buffer->txq.buffer_state_head + 1) % buffer->txq.buffer_state_size; bsm->binding = cc; bsm->offset = offset; ++buffer->txq.buffer_state_used; opaque = (void*)bsm; // save information as list of packet-chunks before sending to HW cl->driver_buff_list[cl->chunk_counter].va = vaddr; cl->driver_buff_list[cl->chunk_counter].pa = paddr; cl->driver_buff_list[cl->chunk_counter].len = length; cl->driver_buff_list[cl->chunk_counter].opaque = opaque; cl->driver_buff_list[cl->chunk_counter].flags = flags; ++cl->chunk_counter; if (more == 0) { // ETHERSRV_DEBUG // printf("sending out packet\n"); if (cl->chunk_counter > 1) { ETHERSRV_DEBUG //printf ("%s:%s: handle=%p\n", disp_name(), __func__, opaque); } err = ether_transmit_pbuf_list_ptr(cl->driver_buff_list, cl->chunk_counter); assert(err_is_ok(err)); cl->chunk_counter = 0; } } else { // RX_BUFFER_ID // Sanity check. Making sure that more flag is not set if (more == 1) { USER_PANIC("broken buffer registerd with for RX buffer\n"); } // Make sure that there is opaque slot available (isfull) assert(buffer->rxq.buffer_state_used < (buffer->rxq.buffer_state_size - 1)); // Save state for handle_tx_done()/handle_receive_packet struct buffer_state_metadata *bsm = buffer->rxq.buffer_state + buffer->rxq.buffer_state_head; buffer->rxq.buffer_state_head = (buffer->rxq.buffer_state_head + 1) % buffer->rxq.buffer_state_size; bsm->binding = cc; bsm->offset = offset; ++buffer->rxq.buffer_state_used; ++rx_added; opaque = (void*)bsm; // role == RX_BUFFER_ID if (use_sf) { // nothing to do! } else { assert(length == rx_buffer_size); rx_register_buffer_fn_ptr(paddr, vaddr, opaque); } // FIXME: send a message back acking receiving of message. } // end else: RX_BUFFER_ID } // end function: raw_add_buffer
int Creature::deal_projectile_attack(Creature *source, double missed_by, const projectile &proj, dealt_damage_instance &dealt_dam) { bool u_see_this = g->u_see(this); body_part bp_hit; int side = rng(0, 1); // do 10,speed because speed could potentially be > 10000 if (dodge_roll() >= dice(10, proj.speed)) { if (is_player()) add_msg(_("You dodge %s projectile!"), source->disp_name(true).c_str()); else if (u_see_this) add_msg(_("%s dodges %s projectile."), disp_name().c_str(), source->disp_name(true).c_str()); return 0; } // Bounce applies whether it does damage or not. if (proj.proj_effects.count("BOUNCE")) { add_effect("bounced", 1); } double hit_value = missed_by + rng_float(-0.5, 0.5); // headshots considered elsewhere if (hit_value <= 0.4) { bp_hit = bp_torso; } else if (one_in(4)) { bp_hit = bp_legs; } else { bp_hit = bp_arms; } double monster_speed_penalty = std::max(double(get_speed()) / 80., 1.0); double goodhit = missed_by / monster_speed_penalty; double damage_mult = 1.0; std::string message = ""; game_message_type gmtSCTcolor = m_neutral; if (goodhit <= .1) { message = _("Headshot!"); source->add_msg_if_player(m_good, message.c_str()); gmtSCTcolor = m_headshot; damage_mult *= rng_float(2.45, 3.35); bp_hit = bp_head; // headshot hits the head, of course } else if (goodhit <= .2) { message = _("Critical!"); source->add_msg_if_player(m_good, message.c_str()); gmtSCTcolor = m_critical; damage_mult *= rng_float(1.75, 2.3); } else if (goodhit <= .4) { message = _("Good hit!"); source->add_msg_if_player(m_good, message.c_str()); gmtSCTcolor = m_good; damage_mult *= rng_float(1, 1.5); } else if (goodhit <= .6) { damage_mult *= rng_float(0.5, 1); } else if (goodhit <= .8) { message = _("Grazing hit."); source->add_msg_if_player(m_good, message.c_str()); gmtSCTcolor = m_grazing; damage_mult *= rng_float(0, .25); } else { damage_mult *= 0; } // copy it, since we're mutating damage_instance impact = proj.impact; if( item(proj.ammo->id, 0).has_flag("NOGIB") ) { impact.add_effect("NOGIB"); } impact.mult_damage(damage_mult); dealt_dam = deal_damage(source, bp_hit, side, impact); dealt_dam.bp_hit = bp_hit; // Apply ammo effects to target. const std::string target_material = get_material(); if (proj.proj_effects.count("FLAME")) { if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") || 0 == target_material.compare("wool") || 0 == target_material.compare("paper") || 0 == target_material.compare("wood" ) ) { add_effect("onfire", rng(8, 20)); } else if (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) { add_effect("onfire", rng(5, 10)); } } else if (proj.proj_effects.count("INCENDIARY") ) { if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") || 0 == target_material.compare("wool") || 0 == target_material.compare("paper") || 0 == target_material.compare("wood") ) { add_effect("onfire", rng(2, 6)); } else if ( (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) && one_in(4) ) { add_effect("onfire", rng(1, 4)); } } else if (proj.proj_effects.count("IGNITE")) { if (0 == target_material.compare("veggy") || 0 == target_material.compare("cotton") || 0 == target_material.compare("wool") || 0 == target_material.compare("paper") || 0 == target_material.compare("wood") ) { add_effect("onfire", rng(6, 6)); } else if (0 == target_material.compare("flesh") || 0 == target_material.compare("iflesh") ) { add_effect("onfire", rng(10, 10)); } } int stun_strength = 0; if (proj.proj_effects.count("BEANBAG")) { stun_strength = 4; } if(proj.proj_effects.count("WHIP")) { stun_strength = rng(4, 10); } if (proj.proj_effects.count("LARGE_BEANBAG")) { stun_strength = 16; } if( stun_strength > 0 ) { switch( get_size() ) { case MS_TINY: stun_strength *= 4; break; case MS_SMALL: stun_strength *= 2; break; case MS_MEDIUM: default: break; case MS_LARGE: stun_strength /= 2; break; case MS_HUGE: stun_strength /= 4; break; } add_effect( "stunned", rng(stun_strength / 2, stun_strength) ); } if(u_see_this) { if (damage_mult == 0) { if(source != NULL) { add_msg(source->is_player() ? _("You miss!") : _("The shot misses!")); } } else if (dealt_dam.total_damage() == 0) { add_msg(_("The shot reflects off %s %s!"), disp_name(true).c_str(), skin_name().c_str()); } else if (source != NULL) { if (source->is_player()) { //player hits monster ranged nc_color color; std::string health_bar = ""; get_HP_Bar(dealt_dam.total_damage(), this->get_hp_max(), color, health_bar, true); SCT.add(this->xpos(), this->ypos(), direction_from(0, 0, this->xpos() - source->xpos(), this->ypos() - source->ypos()), health_bar, m_good, message, gmtSCTcolor); if (this->get_hp() > 0) { get_HP_Bar(this->get_hp(), this->get_hp_max(), color, health_bar, true); SCT.add(this->xpos(), this->ypos(), direction_from(0, 0, this->xpos() - source->xpos(), this->ypos() - source->ypos()), health_bar, m_good, "hp", m_neutral, "hp"); } else { SCT.removeCreatureHP(); } add_msg(m_good, _("You hit the %s for %d damage."), disp_name().c_str(), dealt_dam.total_damage()); } else if(this->is_player()) { //monster hits player ranged add_msg_if_player( m_bad, _( "You were hit in the %s for %d damage." ), body_part_name( bp_hit, side ).c_str( ), dealt_dam.total_damage( ) ); } else if( u_see_this ) { add_msg(_("%s shoots %s."), source->disp_name().c_str(), disp_name().c_str()); } } } return 0; }