int Random::randomInt() { QMutexLocker locker(global_random_mutex()); SecureArray a = global_random()->nextBytes(sizeof(int)); int x; memcpy(&x, a.data(), a.size()); return x; }
bool haveSecureRandom() { if(!global_check_load()) return false; QMutexLocker locker(global_random_mutex()); if(global_random()->provider()->name() != "default") return true; return false; }
short calculate_damage( struct damage_definition *damage) { short total_damage= damage->base + (damage->random ? global_random()%damage->random : 0); total_damage= FIXED_INTEGERAL_PART(total_damage*damage->scale); /* if this damage was caused by an alien modify it for the current difficulty level */ if (damage->flags&_alien_damage) { switch (dynamic_world->game_information.difficulty_level) { case _wuss_level: total_damage-= total_damage>>1; break; case _easy_level: total_damage-= total_damage>>2; break; /* harder levels do not cause more damage */ } } return total_damage; }
SecureArray Random::randomArray(int size) { QMutexLocker locker(global_random_mutex()); return global_random()->nextBytes(size); }
uchar Random::randomChar() { QMutexLocker locker(global_random_mutex()); return global_random()->nextByte(); }
/* assumes ¶t==1 tick */ void move_projectiles( void) { struct projectile_data *projectile; short projectile_index; for (projectile_index=0,projectile=projectiles;projectile_index<MAXIMUM_PROJECTILES_PER_MAP;++projectile_index,++projectile) { if (SLOT_IS_USED(projectile)) { struct object_data *object= get_object_data(projectile->object_index); // if (!OBJECT_IS_INVISIBLE(object)) { struct projectile_definition *definition= get_projectile_definition(projectile->type); short old_polygon_index= object->polygon; world_point3d new_location, old_location; short obstruction_index, new_polygon_index; new_location= old_location= object->location; /* update our objectÕs animation */ animate_object(projectile->object_index); /* if weÕre supposed to end when our animation loops, check this condition */ if ((definition->flags&_stop_when_animation_loops) && (GET_OBJECT_ANIMATION_FLAGS(object)&_obj_last_frame_animated)) { remove_projectile(projectile_index); } else { world_distance speed= definition->speed; uint32 adjusted_definition_flags = 0; uint16 flags; /* base alien projectile speed on difficulty level */ if (definition->flags&_alien_projectile) { switch (dynamic_world->game_information.difficulty_level) { case _wuss_level: speed-= speed>>3; break; case _easy_level: speed-= speed>>4; break; case _major_damage_level: speed+= speed>>3; break; case _total_carnage_level: speed+= speed>>2; break; } } /* if this is a guided projectile with a valid target, update guidance system */ if ((definition->flags&_guided) && projectile->target_index!=NONE && (dynamic_world->tick_count&1)) update_guided_projectile(projectile_index); if (PROJECTILE_HAS_CROSSED_MEDIA_BOUNDARY(projectile)) adjusted_definition_flags= _penetrates_media; /* move the projectile and check for collisions; if we didnÕt detonate move the projectile and check to see if we need to leave a contrail */ if ((definition->flags&_affected_by_half_gravity) && (dynamic_world->tick_count&1)) projectile->gravity-= GRAVITATIONAL_ACCELERATION; if (definition->flags&_affected_by_gravity) projectile->gravity-= GRAVITATIONAL_ACCELERATION; if (definition->flags&_doubly_affected_by_gravity) projectile->gravity-= 2*GRAVITATIONAL_ACCELERATION; if (film_profile.m1_low_gravity_projectiles && static_world->environment_flags&_environment_low_gravity && static_world->environment_flags&_environment_m1_weapons) { projectile->gravity /= 2; } new_location.z+= projectile->gravity; translate_point3d(&new_location, speed, object->facing, projectile->elevation); if (definition->flags&_vertical_wander) new_location.z+= (global_random()&1) ? WANDER_MAGNITUDE : -WANDER_MAGNITUDE; if (definition->flags&_horizontal_wander) translate_point3d(&new_location, (global_random()&1) ? WANDER_MAGNITUDE : -WANDER_MAGNITUDE, NORMALIZE_ANGLE(object->facing+QUARTER_CIRCLE), 0); if (film_profile.infinity_smg) { definition->flags ^= adjusted_definition_flags; } flags= translate_projectile(projectile->type, &old_location, object->polygon, &new_location, &new_polygon_index, projectile->owner_index, &obstruction_index, 0, false, projectile_index); if (film_profile.infinity_smg) { definition->flags ^= adjusted_definition_flags; } // LP change: set up for penetrating media boundary bool will_go_through = false; if (flags&_projectile_hit) { if ((flags&_projectile_hit_floor) && (definition->flags&_rebounds_from_floor) && projectile->gravity<-MINIMUM_REBOUND_VELOCITY) { play_object_sound(projectile->object_index, definition->rebound_sound); projectile->gravity= - projectile->gravity + (projectile->gravity>>2); /* 0.75 */ } else { short monster_obstruction_index= (flags&_projectile_hit_monster) ? get_object_data(obstruction_index)->permutation : NONE; bool destroy_persistent_projectile= false; if (flags&_projectile_hit_scenery) damage_scenery(obstruction_index); /* cause damage, if we can */ if (!PROJECTILE_HAS_CAUSED_DAMAGE(projectile)) { struct damage_definition *damage= &definition->damage; damage->scale= projectile->damage_scale; if (definition->flags&_becomes_item_on_detonation) { if (monster_obstruction_index==NONE) { struct object_location location; location.p= object->location, location.p.z= 0; location.polygon_index= object->polygon; location.yaw= location.pitch= 0; location.flags= 0; // START Benad // Found it! // With new_item(), current_item_count[item] increases, but not // with try_and_add_player_item(). So reverse the effect of new_item in advance. dynamic_world->current_item_count[projectile->permutation]--; // END Benad new_item(&location, projectile->permutation); destroy_persistent_projectile= true; } else { if(MONSTER_IS_PLAYER(get_monster_data(monster_obstruction_index))) { short player_obstruction_index= monster_index_to_player_index(monster_obstruction_index); destroy_persistent_projectile= try_and_add_player_item(player_obstruction_index, projectile->permutation); } } } else { if (definition->area_of_effect) { damage_monsters_in_radius(monster_obstruction_index, projectile->owner_index, projectile->owner_type, &old_location, object->polygon, definition->area_of_effect, damage, projectile_index); } else { if (monster_obstruction_index!=NONE) damage_monster(monster_obstruction_index, projectile->owner_index, projectile->owner_type, &old_location, damage, projectile_index); } } } if ((definition->flags&_persistent) && !destroy_persistent_projectile) { SET_PROJECTILE_DAMAGE_STATUS(projectile, true); } else { short detonation_effect= definition->detonation_effect; if (monster_obstruction_index!=NONE) { if (definition->flags&_bleeding_projectile) { detonation_effect= get_monster_impact_effect(monster_obstruction_index); } if (definition->flags&_melee_projectile) { short new_detonation_effect= get_monster_melee_impact_effect(monster_obstruction_index); if (new_detonation_effect!=NONE) detonation_effect= new_detonation_effect; } } if (flags&_projectile_hit_media) { get_media_detonation_effect(get_polygon_data(obstruction_index)->media_index, definition->media_detonation_effect, &detonation_effect); // LP addition: check if projectile will hit media and continue (PMB flag) // set will_go_through for later processing if (film_profile.a1_smg) { // Be careful about parentheses here! will_go_through = (definition->flags&_penetrates_media_boundary) != 0; // Push the projectile upward or downward, if necessary if (will_go_through) { if (projectile->elevation == 0) {} else if (projectile->elevation < HALF_CIRCLE) new_location.z++; else if (projectile->elevation > HALF_CIRCLE) new_location.z--; } } } if (film_profile.a1_smg) { // LP addition: don't detonate if going through media // if PMB is set; otherwise, detonate if doing so. // Some of the later routines may set both "hit landscape" and "hit media", // so be careful. if (flags&_projectile_hit_landscape && !(flags&_projectile_hit_media)) detonation_effect= NONE; } else { if (flags&_projectile_hit_landscape) detonation_effect = NONE; } if (detonation_effect!=NONE) new_effect(&new_location, new_polygon_index, detonation_effect, object->facing); L_Call_Projectile_Detonated(projectile->type, projectile->owner_index, new_polygon_index, new_location); if (!film_profile.infinity_smg || (!(definition->flags&_penetrates_media_boundary) || !(flags&_projectile_hit_media))) { if ((definition->flags&_persistent_and_virulent) && !destroy_persistent_projectile && monster_obstruction_index!=NONE) { bool reassign_projectile = true; if (film_profile.prevent_dead_projectile_owners) { monster_data *monster = get_monster_data(monster_obstruction_index); reassign_projectile = MONSTER_IS_PLAYER(monster) || !MONSTER_IS_DYING(monster); } if (reassign_projectile) projectile->owner_index= monster_obstruction_index; /* keep going, but donÕt hit this target again */ } // LP addition: don't remove a projectile that will hit media and continue (PMB flag) else if (!will_go_through) { remove_projectile(projectile_index); } } else if (film_profile.infinity_smg) { SET_PROJECTILE_CROSSED_MEDIA_BOUNDARY_STATUS(projectile, true); } } } } // Move the projectile if it hit nothing or it will go through media surface if (!(flags&_projectile_hit) || will_go_through) // else { /* move to the new_polygon_index */ translate_map_object(projectile->object_index, &new_location, new_polygon_index); /* should we leave a contrail at our old location? */ if ((projectile->ticks_since_last_contrail+=1)>=definition->ticks_between_contrails) { if (definition->maximum_contrails==NONE || projectile->contrail_count<definition->maximum_contrails) { projectile->contrail_count+= 1; projectile->ticks_since_last_contrail= 0; if (definition->contrail_effect!=NONE) new_effect(&old_location, old_polygon_index, definition->contrail_effect, object->facing); } } if ((flags&_flyby_of_current_player) && !PROJECTILE_HAS_MADE_A_FLYBY(projectile)) { SET_PROJECTILE_FLYBY_STATUS(projectile, true); play_object_sound(projectile->object_index, definition->flyby_sound); } /* if we have a maximum range and we have exceeded it then remove the projectile */ if (definition->maximum_range!=NONE) { if ((projectile->distance_travelled+= speed)>=definition->maximum_range) { remove_projectile(projectile_index); } } } } } }
short new_projectile( world_point3d *origin, short polygon_index, world_point3d *_vector, angle delta_theta, /* ±¶theta is added (in a circle) to the angle before firing */ short type, short owner_index, short owner_type, short intended_target_index, /* can be NONE */ _fixed damage_scale) { struct projectile_definition *definition; struct projectile_data *projectile; short projectile_index; type= adjust_projectile_type(origin, polygon_index, type, owner_index, owner_type, intended_target_index, damage_scale); definition= get_projectile_definition(type); for (projectile_index= 0, projectile= projectiles; projectile_index<MAXIMUM_PROJECTILES_PER_MAP; ++projectile_index, ++projectile) { if (SLOT_IS_FREE(projectile)) { angle facing, elevation; short object_index; struct object_data *object; facing= arctangent(_vector->x, _vector->y); elevation= arctangent(isqrt(_vector->x*_vector->x+_vector->y*_vector->y), _vector->z); if (delta_theta) { if (!(definition->flags&_no_horizontal_error)) facing= normalize_angle(facing+global_random()%(2*delta_theta)-delta_theta); if (!(definition->flags&_no_vertical_error)) elevation= (definition->flags&_positive_vertical_error) ? normalize_angle(elevation+global_random()%delta_theta) : normalize_angle(elevation+global_random()%(2*delta_theta)-delta_theta); } object_index= new_map_object3d(origin, polygon_index, definition->collection==NONE ? NONE : BUILD_DESCRIPTOR(definition->collection, definition->shape), facing); if (object_index!=NONE) { object= get_object_data(object_index); projectile->type= (definition->flags&_alien_projectile) ? (alien_projectile_override==NONE ? type : alien_projectile_override) : (human_projectile_override==NONE ? type : human_projectile_override); projectile->object_index= object_index; projectile->owner_index= owner_index; projectile->target_index= intended_target_index; projectile->owner_type= owner_type; projectile->flags= 0; projectile->gravity= 0; projectile->ticks_since_last_contrail= projectile->contrail_count= 0; projectile->elevation= elevation; projectile->distance_travelled= 0; projectile->damage_scale= damage_scale; MARK_SLOT_AS_USED(projectile); SET_OBJECT_OWNER(object, _object_is_projectile); object->sound_pitch= definition->sound_pitch; L_Call_Projectile_Created(projectile_index); } else { projectile_index= NONE; } break; } } if (projectile_index==MAXIMUM_PROJECTILES_PER_MAP) projectile_index= NONE; return projectile_index; }