/** * Basic single-frame area hazard */ bool PowerManager::single(int power_index, StatBlock *src_stats, Point target) { Hazard *haz = new Hazard(); // common to all singles haz->pos.x = (float)target.x; haz->pos.y = (float)target.y; haz->lifespan = 1; haz->crit_chance = src_stats->crit; haz->accuracy = src_stats->accuracy; haz->src_stats = src_stats; // specific powers have different stats here if (power_index == POWER_VENGEANCE) { haz->pos = calcVector(src_stats->pos, src_stats->direction, src_stats->melee_range); haz->dmg_min = src_stats->dmg_melee_min; haz->dmg_max = src_stats->dmg_melee_max; haz->radius = 64; src_stats->mp--; // use vengeance stacks haz->accuracy += src_stats->vengeance_stacks * 25; haz->crit_chance += src_stats->vengeance_stacks * 25; src_stats->vengeance_stacks = 0; } hazards.push(haz); // Hazard memory is now the responsibility of HazardManager return true; }
/*----------------------------------------------------------------------------*/ static void enableInterrupt(const struct PinInterrupt *interrupt) { const IrqNumber irq = calcVector(interrupt->channel); LPC_GPIO_INT->IST = 1UL << interrupt->pin.offset; irqClearPending(irq); irqEnable(irq); }
/** * Set a target depending on how a power was triggered */ FPoint MenuActionBar::setTarget(bool have_aim, bool aim_assist) { if (have_aim && MOUSE_AIM) { if (aim_assist) return screen_to_map(inpt->mouse.x, inpt->mouse.y + AIM_ASSIST, pc->stats.pos.x, pc->stats.pos.y); else return screen_to_map(inpt->mouse.x, inpt->mouse.y, pc->stats.pos.x, pc->stats.pos.y); } else { return calcVector(pc->stats.pos, pc->stats.direction, pc->stats.melee_range); } }
/*----------------------------------------------------------------------------*/ static enum Result pinInterruptInit(void *object, const void *configBase) { const struct PinInterruptConfig * const config = configBase; assert(config); const struct Pin input = pinInit(config->pin); assert(pinValid(input)); /* Try to allocate a new channel */ struct PinInterrupt * const interrupt = object; const int channel = setInstance(interrupt); if (channel == -1) return E_BUSY; /* Configure the pin */ pinInput(input); pinSetPull(input, config->pull); interrupt->callback = 0; interrupt->channel = channel; interrupt->enabled = false; interrupt->event = config->event; interrupt->pin = input.data; const uint8_t index = interrupt->channel >> 2; const uint32_t mask = 1UL << interrupt->channel; /* Enable peripheral */ if (!sysClockStatus(CLK_PINT)) sysClockEnable(CLK_PINT); /* Select pin and port */ LPC_SYSCON->PINTSEL[index] = (LPC_SYSCON->PINTSEL[index] & ~PINTSEL_CHANNEL_MASK(channel)) | PINTSEL_CHANNEL(channel, input.data.port, input.data.offset); /* Configure interrupt as edge sensitive */ LPC_GPIO_INT->ISEL &= ~mask; /* Configure edge sensitivity options */ if (config->event == PIN_RISING || config->event == PIN_TOGGLE) LPC_GPIO_INT->SIENR = mask; if (config->event == PIN_FALLING || config->event == PIN_TOGGLE) LPC_GPIO_INT->SIENF = mask; #ifdef CONFIG_PM /* Interrupt will wake the controller from low-power modes */ LPC_SYSCON->STARTERP0 |= STARTERP0_PINT(interrupt->channel); #endif /* Configure interrupt priority, interrupt is disabled by default */ irqSetPriority(calcVector(interrupt->channel), config->priority); return E_OK; }
void ListWeatherCloud::renderClouds(){ //if (cycle_i > time_of_rain) renderRainfall(); renderRainfall(); // TODO: remove this line, uncomment previous if ( (clouds_arr_initialized) && (!cloud_list.empty()) ){ std::list<WeatherCloud*>::iterator it=cloud_list.begin(); WeatherCloud *cloud; Sprite *spr_cloud; Point p; FPoint fp; Point dest_p; int i, j, nr=0; i=-RADIUS; j=0; // -> with j=-RADIUS: segmentation faults quite common while (j < RADIUS){ // use a cloud from the list several times if needed if ((it == cloud_list.end())) it=cloud_list.begin(); cloud = *it; if (cloud==NULL){ it++; continue; // break; } spr_cloud = cloud->getSprite(); if (spr_cloud==NULL) break; fp.x = cloud_state[nr][4] + i; fp.y = cloud_state[nr][5] + j; if (!isWithin(mapr->cam,RADIUS + 4,fp)){ // move cloud to the opposite direction direction = calcDirection(mapr->cam.x, mapr->cam.y, fp.x, fp.y); if (direction < 4) direction +=4; else direction -=4; FPoint fpn = calcVector(fp, direction, RADIUS+24); cloud_state[nr][4] = floor(fpn.x) - i; cloud_state[nr][5] = floor(fpn.y) - j; } p = map_to_screen(cloud_state[nr][4] + i, cloud_state[nr][5] + j, mapr->cam.x, mapr->cam.y); if (cycle_i % RENDER_CHANGE_AFTER/2 == 0) { // TODO: should depend on wind direction and perhaps speed; cloud_state[nr][2] = cloud_state[nr][2] + randBetween(1,2); cloud_state[nr][3] = cloud_state[nr][3] + randBetween(1,2); direction = calcDirection(0.0,0.0, cloud_state[nr][2], cloud_state[nr][3]); } // overflow of cloud_state[nr][2] possible, but with little consequences dest_p.x = p.x + (cloud_state[nr][2] % 800) - 400; dest_p.y = p.y + (cloud_state[nr][3] % 600) - 300; spr_cloud->setOffset(cloud_state[nr][1],cloud_state[nr][1]); spr_cloud->setDest(dest_p); render_device->render(spr_cloud); i+=cloud_distance; if (i>RADIUS){ i=-RADIUS; j+=cloud_distance; } it++; nr++; } } }
void Avatar::handlePower(std::vector<ActionData> &action_queue) { bool blocking = false; for (unsigned i=0; i<action_queue.size(); i++) { ActionData &action = action_queue[i]; const Power &power = powers->getPower(action.power); if (power.type == POWTYPE_BLOCK) blocking = true; if (action.power != 0 && (stats.cooldown_ticks == 0 || action.instant_item)) { FPoint target = action.target; // check requirements if ((stats.cur_state == AVATAR_ATTACK || stats.cur_state == AVATAR_HIT) && !action.instant_item) continue; if (!stats.canUsePower(power, action.power)) continue; if (power.requires_los && !mapr->collider.line_of_sight(stats.pos.x, stats.pos.y, target.x, target.y)) continue; if (power.requires_empty_target && !mapr->collider.is_empty(target.x, target.y)) continue; if (hero_cooldown[action.power] > 0) continue; if (!powers->hasValidTarget(action.power, &stats, target)) continue; // automatically target the selected enemy with melee attacks if (power.type == POWTYPE_FIXED && power.starting_pos == STARTING_POS_MELEE && enemy_pos.x != -1 && enemy_pos.y != -1) { target = enemy_pos; } // is this a power that requires changing direction? if (power.face) { stats.direction = calcDirection(stats.pos, target); } // draw a target on the ground if we're attacking if (!power.buff && !power.buff_teleport && power.type != POWTYPE_TRANSFORM && power.type != POWTYPE_BLOCK && !(power.starting_pos == STARTING_POS_SOURCE && power.speed == 0)) { if (power.starting_pos == STARTING_POS_TARGET && power.target_range > 0) { target_pos = clampDistance(power.target_range, stats.pos, target); } else if (power.starting_pos == STARTING_POS_MELEE) { target_pos = calcVector(stats.pos, stats.direction, stats.melee_range); } else { target_pos = target; } if (target_anim) { target_visible = true; target_anim->reset(); } lock_cursor = true; } else { curs->setCursor(CURSOR_NORMAL); } if (power.new_state != POWSTATE_INSTANT) { current_power = action.power; act_target = target; attack_anim = power.attack_anim; } if (power.state_duration > 0) stats.state_ticks = power.state_duration; if (power.charge_speed != 0.0f) stats.charge_speed = power.charge_speed; switch (power.new_state) { case POWSTATE_ATTACK: // handle attack powers stats.cur_state = AVATAR_ATTACK; break; case POWSTATE_INSTANT: // handle instant powers powers->activate(action.power, &stats, target); hero_cooldown[action.power] = power.cooldown; break; default: if (power.type == POWTYPE_BLOCK) { stats.cur_state = AVATAR_BLOCK; powers->activate(action.power, &stats, target); hero_cooldown[action.power] = power.cooldown; stats.refresh_stats = true; } break; } } } stats.blocking = blocking; }
/** * Apply basic power info to a new hazard. * * This can be called several times to combine powers. * Typically done when a base power can be modified by equipment * (e.g. ammo type affects the traits of powers that shoot) * * @param power_index The activated power ID * @param src_stats The StatBlock of the power activator * @param target Aim position in map coordinates * @param haz A newly-initialized hazard */ void PowerManager::initHazard(int power_index, StatBlock *src_stats, Point target, Hazard *haz) { //the hazard holds the statblock of its source haz->src_stats = src_stats; // Hazard attributes based on power source haz->crit_chance = src_stats->crit; haz->accuracy = src_stats->accuracy; // Hazard damage depends on equipped weapons and the power's optional damage_multiplier if (powers[power_index].base_damage == BASE_DAMAGE_MELEE) { haz->dmg_min = src_stats->dmg_melee_min; haz->dmg_max = src_stats->dmg_melee_max; } else if (powers[power_index].base_damage == BASE_DAMAGE_RANGED) { haz->dmg_min = src_stats->dmg_ranged_min; haz->dmg_max = src_stats->dmg_ranged_max; } else if (powers[power_index].base_damage == BASE_DAMAGE_MENT) { haz->dmg_min = src_stats->dmg_ment_min; haz->dmg_max = src_stats->dmg_ment_max; } //apply the multiplier haz->dmg_min = ceil(haz->dmg_min * powers[power_index].damage_multiplier / 100.0); haz->dmg_max = ceil(haz->dmg_max * powers[power_index].damage_multiplier / 100.0); // Only apply stats from powers that are not defaults // If we do this, we can init with multiple power layers // (e.g. base spell plus weapon type) if (powers[power_index].gfx_index != -1) { haz->sprites = gfx[powers[power_index].gfx_index]; } if (powers[power_index].rendered) { haz->rendered = powers[power_index].rendered; } if (powers[power_index].lifespan != 0) { haz->lifespan = powers[power_index].lifespan; } if (powers[power_index].frame_loop != 1) { haz->frame_loop = powers[power_index].frame_loop; } if (powers[power_index].frame_duration != 1) { haz->frame_duration = powers[power_index].frame_duration; } if (powers[power_index].frame_size.x != 0) { haz->frame_size.x = powers[power_index].frame_size.x; } if (powers[power_index].frame_size.y != 0) { haz->frame_size.y = powers[power_index].frame_size.y; } if (powers[power_index].frame_offset.x != 0) { haz->frame_offset.x = powers[power_index].frame_offset.x; } if (powers[power_index].frame_offset.y != 0) { haz->frame_offset.y = powers[power_index].frame_offset.y; } if (powers[power_index].directional) { haz->direction = calcDirection(src_stats->pos.x, src_stats->pos.y, target.x, target.y); } else if (powers[power_index].visual_random != 0) { haz->visual_option = rand() % powers[power_index].visual_random; } else if (powers[power_index].visual_option != 0) { haz->visual_option = powers[power_index].visual_option; } haz->floor = powers[power_index].floor; if (powers[power_index].speed > 0) { haz->base_speed = powers[power_index].speed; } if (powers[power_index].complete_animation) { haz->complete_animation = true; } // combat traits if (powers[power_index].no_attack) { haz->active = false; } if (powers[power_index].multitarget) { haz->multitarget = true; } if (powers[power_index].active_frame != -1) { haz->active_frame = powers[power_index].active_frame; } if (powers[power_index].radius != 0) { haz->radius = powers[power_index].radius; } if (powers[power_index].trait_armor_penetration) { haz->trait_armor_penetration = true; } haz->trait_crits_impaired = powers[power_index].trait_crits_impaired; if (powers[power_index].trait_elemental) { haz->trait_elemental = powers[power_index].trait_elemental; } // status effect durations // durations stack when combining powers (e.g. base power and weapon/ammo type) haz->bleed_duration += powers[power_index].bleed_duration; haz->stun_duration += powers[power_index].stun_duration; haz->slow_duration += powers[power_index].slow_duration; haz->immobilize_duration += powers[power_index].immobilize_duration; // steal effects haz->hp_steal += powers[power_index].hp_steal; haz->mp_steal += powers[power_index].mp_steal; // hazard starting position if (powers[power_index].starting_pos == STARTING_POS_SOURCE) { haz->pos.x = (float)src_stats->pos.x; haz->pos.y = (float)src_stats->pos.y; } else if (powers[power_index].starting_pos == STARTING_POS_TARGET) { haz->pos.x = (float)target.x; haz->pos.y = (float)target.y; } else if (powers[power_index].starting_pos == STARTING_POS_MELEE) { haz->pos = calcVector(src_stats->pos, src_stats->direction, src_stats->melee_range); } // pre/post power effects if (powers[power_index].post_power != -1) { haz->post_power = powers[power_index].post_power; } if (powers[power_index].wall_power != -1) { haz->wall_power = powers[power_index].wall_power; } // if equipment has special powers, apply it here (if it hasn't already been applied) if (!haz->equipment_modified && powers[power_index].allow_power_mod) { if (powers[power_index].base_damage == BASE_DAMAGE_MELEE && src_stats->melee_weapon_power != -1) { haz->equipment_modified = true; initHazard(src_stats->melee_weapon_power, src_stats, target, haz); } else if (powers[power_index].base_damage == BASE_DAMAGE_MENT && src_stats->mental_weapon_power != -1) { haz->equipment_modified = true; initHazard(src_stats->mental_weapon_power, src_stats, target, haz); } else if (powers[power_index].base_damage == BASE_DAMAGE_RANGED && src_stats->ranged_weapon_power != -1) { haz->equipment_modified = true; initHazard(src_stats->ranged_weapon_power, src_stats, target, haz); } } }
/*----------------------------------------------------------------------------*/ static void disableInterrupt(const struct PinInterrupt *interrupt) { irqDisable(calcVector(interrupt->channel)); }