Merge pull request #448 from mastercheese-dev/plasma-charge

Draw the plasma pistol's charge with the picture, and keep the meter's values.
This commit is contained in:
bnunu authored and GitHub committed 2026-10-27 02:46:56 -04:00
commit bf58c8d985
5 files changed
+299 -109

No files matched your search

+18 -3
View File
@@ -117,6 +117,7 @@ symbols in this file:
#include "models/models.h"
#include "networking/network_connection.h"
#include "objects/objects.h"
#include "rasterizer/rasterizer.h" /* port: rasterizer_memory_alloc */
#include "rasterizer/rasterizer_model_types.h"
#include "render/render.h"
#include "saved games/game_state.h"
@@ -509,7 +510,21 @@ void first_person_weapon_draw(
struct animation_graph *animation_graph= animation_graph_definition_get(
weapon_definition->weapon.interface_definition.first_person_animations.index);
struct render_lighting *lighting= object_get_cached_render_lighting(unit_index, FLT_MAX);
real values[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS];
real const *weapon_functions = weapon->object.outgoing_function_values;
real const *unit_functions = unit->object.outgoing_function_values;
real *kept;
/* port: the tick's functions, moved into this frame, so the
charge clicks with the picture instead of once a tick; kept
in the rasterizer's memory for the frame, as the groups drawn
later read them (render_objects.c) */
object_function_values_for_render(first_person_weapon->weapon_index, values);
if ((kept = rasterizer_memory_alloc(values, sizeof(values))) != NULL)
weapon_functions = kept;
object_function_values_for_render(unit_index, values);
if ((kept = rasterizer_memory_alloc(values, sizeof(values))) != NULL)
unit_functions = kept;
model_effect.modifier_shader= NULL;
if (TEST_FLAG(unit->unit.flags, _unit_active_camouflaged_bit) ||
unit->unit.active_camouflage>0.0f)
@@ -540,7 +555,7 @@ void first_person_weapon_draw(
model_node_matrices,
NULL,
weapon->object.outgoing_change_colors,
weapon->object.outgoing_function_values,
weapon_functions,
lighting,
&render.camera.position,
0.0f,
@@ -569,7 +584,7 @@ void first_person_weapon_draw(
model_effect.modifier_animation.colors= shield_color_colors(unit_index,
unit->object.outgoing_change_colors);
model_effect.modifier_animation.values= overshield_effect_values(unit_index,
unit->object.outgoing_function_values, TRUE);
unit_functions, TRUE);
}
}
}
@@ -589,7 +604,7 @@ void first_person_weapon_draw(
model_node_matrices,
NULL,
unit->object.outgoing_change_colors,
unit->object.outgoing_function_values,
unit_functions,
lighting,
&render.camera.position,
0.0f,
+248 -102
View File
@@ -97,6 +97,19 @@ index, which reads no function: 0 */
#define OBJECT_FRAME_INDEX_GET(object_index) ((object_index) + game_time_get())
/* port: set while a frame is drawn, so a function read for the picture is
the tick's value moved into the frame */
static int object_function_render_depth = 0;
static real object_function_addition(
struct object_datum *object,
struct object_function_definition *function,
real huh,
real const *outgoing,
boolean *active);
static real object_function_wrap(
real value);
/* ---------- structures */
struct object_globals
@@ -1550,6 +1563,77 @@ void object_permute_region(
return;
}
void object_functions_set_for_render(
boolean for_render)
{
if (for_render)
object_function_render_depth++;
else if (object_function_render_depth > 0)
object_function_render_depth--;
}
void object_function_values_for_render(
long object_index,
real values[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS])
{
struct object_datum *object = object_get(object_index);
struct object_definition *definition = object_definition_get(object->definition_index);
/* port: where the picture is, between the previous tick (0) and this one
(1) (render_interpolation.c); 1 outside an interpolated frame (Smooth
Motion off), where the tick's own values are shown */
real fraction = render_interpolation_fraction();
short function_count = (short)MIN(
definition->object.functions.count,
NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS);
short function_index;
real huh;
real back;
csmemcpy(
values,
object->object.outgoing_function_values,
sizeof(object->object.outgoing_function_values));
if (!(fraction >= 0.0f) || !(fraction < 1.0f))
return;
back = 1.0f - fraction;
huh = (57 * DATUM_INDEX_TO_ABSOLUTE_INDEX(object_index) + game_time_get()) * 0.033333335f;
for (function_index = 0; function_index < function_count; function_index++)
{
struct object_function_definition *function = TAG_BLOCK_GET_ELEMENT(
&definition->object.functions,
function_index,
struct object_function_definition);
boolean active;
real output;
/* port: an additive function steps by a whole tick: the picture
is that part of the step back from this tick's value. Anything else
is the function at the picture's moment. */
if (TEST_FLAG(function->flags, _object_function_clip_to_bounds_and_normalize))
{
output = object_function_addition(
object,
function,
huh,
object->object.outgoing_function_values,
&active);
values[function_index] = object_function_wrap(
object->object.outgoing_function_values[function_index] - back * output);
}
else
{
output = object_function_addition(
object,
function,
huh - back * 0.033333335f,
values,
&active);
values[function_index] = output;
}
}
}
boolean object_get_function_value(
long object_index,
short function_index,
@@ -1573,7 +1657,17 @@ boolean object_get_function_value(
it reads as off */
if (VALID_INDEX(function_index, NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS))
{
*value_reference = object->object.outgoing_function_values[function_index];
if (object_function_render_depth > 0)
{
real shown[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS];
object_function_values_for_render(object_index, shown);
*value_reference = shown[function_index];
}
else
{
*value_reference = object->object.outgoing_function_values[function_index];
}
result = TEST_FLAG(object->object.functions_active_flags, function_index);
}
@@ -5175,6 +5269,150 @@ static void object_delete_recursive(
return;
}
static real object_function_input_value(
struct object_datum *object,
real const *outgoing,
short index)
{
if ((unsigned long)(index - 1) >=
(unsigned long)(NUMBER_OF_INCOMING_OBJECT_FUNCTIONS + NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS))
return 0.0f;
if (index >= NUMBER_OF_INCOMING_OBJECT_FUNCTIONS + 1)
return outgoing[index - NUMBER_OF_INCOMING_OBJECT_FUNCTIONS - 1];
return object->object.incoming_function_values[index - 1];
}
static real object_function_wrap(
real value)
{
value -= (real)floor((double)value);
if (!(value >= 0.0f))
value += 1.0f;
return value;
}
/* port: the original's loop body, as one function, so that the picture's
values (object_function_values_for_render) are found as the tick's are: what
one tick stores, before an additive function folds it into the value it
already held. `outgoing` is the functions already computed. */
static real object_function_addition(
struct object_datum *object,
struct object_function_definition *function,
real huh,
real const *outgoing,
boolean *active)
{
real value;
real output;
boolean function_is_active = TRUE;
real period = function->runtime_one_over_period;
if (function->scale_period_by_function_index)
{
real function_value = object_function_input_value(
object,
outgoing,
function->scale_period_by_function_index);
if (function_value > 0.f)
period = period / function_value;
}
value = periodic_function_evaluate(function->function_type, huh * period);
if (function->scale_function_by_function_index)
{
value *= object_function_input_value(
object,
outgoing,
function->scale_function_by_function_index);
}
if (TEST_FLAG(function->flags, _object_function_invert_function_bit))
value = 1.f - value;
if (function->wobble_magnitude != 0.f)
{
real val = periodic_function_evaluate(
function->wobble_function_type,
huh * function->wobble_period);
value += (2.f * function->wobble_magnitude * (val - 0.5f));
}
if (function->square_wave_threshold != 0.f)
value = value > function->square_wave_threshold ? 1.f : 0.f;
if (function->step_count > 1)
{
real floor_value = floor(function->step_count * value);
value = floor_value * function->runtime_reciprocal_step_count;
}
if (function->runtime_reciprocal_sawtooth_count > 0.f)
value = fmod(value, function->runtime_reciprocal_sawtooth_count);
if (function->add_function_index)
{
value += object_function_input_value(object, outgoing, function->add_function_index);
value = MIN(value, 1.f);
}
if (function->scale_result_by_function_index)
{
value *= object_function_input_value(
object,
outgoing,
function->scale_result_by_function_index);
}
output = transition_function_evaluate(function->map_result_to_transition_function, value);
if (function->scale_by > 0.f)
output *= function->scale_by;
if (function->bounds_mode == _object_function_scale_to_fit_bounds)
{
output *= (function->upper_bound - function->lower_bound);
output += function->lower_bound;
if (function->lower_bound + _real_epsilon >= output)
{
function_is_active = TEST_FLAG(
function->flags,
_object_function_does_not_deactivate_below_lower_bound_bit);
}
}
else
{
if (function->lower_bound + _real_epsilon >= output)
{
output = function->lower_bound;
function_is_active = TEST_FLAG(
function->flags,
_object_function_does_not_deactivate_below_lower_bound_bit);
}
if (output > function->upper_bound)
output = function->upper_bound;
if (function->bounds_mode == _object_function_clip_to_bounds_and_normalize)
{
output = (output - function->lower_bound) * function->runtime_reciprocal_bounds_range;
}
}
if (function->turn_off_with_function_index != NONE &&
!TEST_FLAG(object->object.functions_active_flags, function->turn_off_with_function_index))
{
function_is_active = FALSE;
}
*active = function_is_active;
return output;
}
static void object_compute_function_values(
long object_index)
{
@@ -5194,112 +5432,20 @@ static void object_compute_function_values(
for (function_index = 0; function_index<function_count; ++function_index)
{
real value;
real output;
struct object_function_definition* function = TAG_BLOCK_GET_ELEMENT(
&object_definition->object.functions,
function_index,
struct object_function_definition);
boolean function_is_active = TRUE;
real period = function->runtime_one_over_period;
if (function->scale_period_by_function_index)
{
real function_value = OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_period_by_function_index);
if (function_value>0.f)
{
period = period/function_value;
}
}
value = periodic_function_evaluate(function->function_type, huh*period);
if (function->scale_function_by_function_index)
{
value*= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_function_by_function_index);
}
if (TEST_FLAG(function->flags, _object_function_invert_function_bit))
{
value = 1.f-value;
}
if (function->wobble_magnitude!=0.f)
{
real val = periodic_function_evaluate(function->wobble_function_type, huh*function->wobble_period);
value+= (2.f*function->wobble_magnitude * (val-0.5f));
}
if (function->square_wave_threshold!=0.f)
{
value = value>function->square_wave_threshold ? 1.f : 0.f ;
}
if (function->step_count>1)
{
real floor_value = floor(function->step_count*value);
value = floor_value*function->runtime_reciprocal_step_count;
}
if (function->runtime_reciprocal_sawtooth_count>0.f)
{
value = fmod(value, function->runtime_reciprocal_sawtooth_count);
}
if (function->add_function_index)
{
value+= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->add_function_index);
value = MIN(value, 1.f);
}
if (function->scale_result_by_function_index)
{
value*= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_result_by_function_index);
}
output = transition_function_evaluate(function->map_result_to_transition_function, value);
if (function->scale_by>0.f)
{
output*= function->scale_by;
}
if (function->bounds_mode==_object_function_scale_to_fit_bounds)
{
output*= (function->upper_bound-function->lower_bound);
output+= function->lower_bound;
if (function->lower_bound+_real_epsilon>=output)
{
function_is_active = TEST_FLAG(function->flags, _object_function_does_not_deactivate_below_lower_bound_bit);
}
}
else
{
if (function->lower_bound+_real_epsilon>=output)
{
output = function->lower_bound;
function_is_active = TEST_FLAG(function->flags, _object_function_does_not_deactivate_below_lower_bound_bit);
}
if (output>function->upper_bound)
{
output = function->upper_bound;
}
if (function->bounds_mode==_object_function_clip_to_bounds_and_normalize)
{
output = (output-function->lower_bound)*function->runtime_reciprocal_bounds_range;
}
}
if (function->turn_off_with_function_index!=NONE &&
!TEST_FLAG(object->object.functions_active_flags, function->turn_off_with_function_index))
{
function_is_active = FALSE;
}
boolean function_is_active;
real output = object_function_addition(
object,
function,
huh,
object->object.outgoing_function_values,
&function_is_active);
/* bit 1 is the additive function (the bounds-mode name shares its
value). It folds this tick onto the value already held. */
if (TEST_FLAG(function->flags, _object_function_clip_to_bounds_and_normalize))
{
output = fmod(output+object->object.outgoing_function_values[function_index], 1.f);
+5
View File
@@ -430,6 +430,11 @@ void object_start_interpolation(long object_index, short frame_count);
void object_offset_interpolation(long object_index, real_vector3d *offset);
void object_permute_region(long object_index, char *permutation_name, short desired_region_index, boolean active_flag);
boolean object_get_function_value(long object_index, short function_index, real *value_reference);
/* port: the picture is drawn between ticks. While this is set, a function
read for drawing is the tick's value moved forward by the fraction of the
tick that has passed. */
void object_functions_set_for_render(boolean for_render);
void object_function_values_for_render(long object_index, real values[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS]);
short objects_in_clusters_by_indices(unsigned long class_flags, short cluster_count, short const *cluster_indices, short maximum_object_count, long *object_indices);
long object_index_from_name_index(short name_index);
/* port: this object takes a scenario name nobody holds, the way a placed
+2
View File
@@ -325,6 +325,7 @@ static void render_window(
render.local_player_index = local_player_index;
render.camera = *camera;
render.frustum = *frustum;
object_functions_set_for_render(TRUE);
parameters.camera = *rasterizer_camera;
parameters.frustum = *rasterizer_frustum;
parameters.rasterizer_target = rasterizer_target;
@@ -444,6 +445,7 @@ static void render_window(
rasterizer_debug_draw();
rasterizer_window_end();
profile_render_window_end();
object_functions_set_for_render(FALSE);
return;
}
+26 -4
View File
@@ -486,6 +486,13 @@ static void render_object_list(
real_matrix4x3 const *node_matrices = legs ?
first_person_legs_node_matrices(object_index, object_get_node_matrices(object_index)) :
object_get_node_matrices(object_index);
/* port: the function values the picture shows
(object_function_values_for_render), kept in the rasterizer's memory
for the frame: a modifier's group, a queued transparent part and a
child that copies this modifier read them after this block is done,
and the overshield finds its own values by their address
(overshield_effect.c), so they are not copied again */
real const *shown_functions = object->object.outgoing_function_values;
if (!object_is_first_person_camera(object_index) || render.camera.mirrored || (legs && node_matrices))
{
@@ -529,6 +536,17 @@ static void render_object_list(
if (!data->shadow)
{
/* port: the tick's functions, moved into this frame, so a
charge clicks with the picture instead of once a tick */
{
real values[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS];
real *kept;
object_function_values_for_render(object_index, values);
kept = rasterizer_memory_alloc(values, sizeof(values));
if (kept)
shown_functions = kept;
}
if (definition->object.modifier_shader.index != NONE)
{
model_effect.modifier_shader = shader_definition_get(
@@ -546,8 +564,8 @@ static void render_object_list(
(port/linux/game/overshield_effect.c) */
model_effect.modifier_animation.values =
TEST_FLAG(_object_mask_unit, object->object.type) ?
overshield_effect_values(object_index, object->object.outgoing_function_values, FALSE) :
object->object.outgoing_function_values;
overshield_effect_values(object_index, shown_functions, FALSE) :
shown_functions;
}
else
{
@@ -629,7 +647,7 @@ static void render_object_list(
node_matrices,
object->object.region_permutations,
object->object.outgoing_change_colors,
object->object.outgoing_function_values,
shown_functions,
data->lighting,
&object->object.bounding_sphere_center,
object->object.bounding_sphere_radius,
@@ -665,9 +683,13 @@ static void render_object_list(
if (!data->shadow && !legs && object->object.first_widget_index != NONE)
{
struct render_animation animation;
real widget_functions[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS];
/* port: the tick's functions, moved into this frame (the
widgets read them as they are drawn, here) */
object_function_values_for_render(object_index, widget_functions);
animation.colors = object->object.outgoing_change_colors;
animation.values = object->object.outgoing_function_values;
animation.values = widget_functions;
widgets_render(object_index, data->lighting, &animation);
}