File: muzzleflash.cpp

package info (click to toggle)
freespace2 25.0.0~rc11%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 47,232 kB
  • sloc: cpp: 657,500; ansic: 22,305; sh: 293; python: 200; makefile: 198; xml: 181
file content (225 lines) | stat: -rw-r--r-- 6,384 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/

#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "math/vecmat.h"
#include "object/object.h"
#include "parse/parselo.h"
#include "particle/particle.h"
#include "particle/ParticleEffect.h"
#include "weapon/muzzleflash.h"
#include "model/modelrender.h"


// ---------------------------------------------------------------------------------------------------------------------
// MUZZLE FLASH DEFINES/VARS
// 

// muzzle flash info - read from a table
typedef struct mflash_blob_info {
	char name[MAX_FILENAME_LEN];
	float offset;
	float radius;

	mflash_blob_info( const mflash_blob_info& mbi )
	{
		strcpy_s( name, mbi.name );
		offset = mbi.offset;
		radius = mbi.radius;
	}

	mflash_blob_info() :
		offset( 0.0 ),
		radius( 0.0 )
	{ 
		name[ 0 ] = '\0';
	}

	mflash_blob_info& operator=( const mflash_blob_info& r )
	{
		strcpy_s( name, r.name );
		offset = r.offset;
		radius = r.radius;

		return *this;
	}
} mflash_blob_info;

typedef struct mflash_info {
	char name[MAX_FILENAME_LEN];
	SCP_vector<mflash_blob_info> blobs;

	mflash_info()
	{ 
		name[ 0 ] = '\0';
	}

	mflash_info( const mflash_info& mi )
	{
		strcpy_s( name, mi.name );
		blobs = mi.blobs;
	}

	mflash_info& operator=( const mflash_info& r )
	{
		strcpy_s( name, r.name );
		blobs = r.blobs;

		return *this;
	}
} mflash_info;

SCP_vector<mflash_info> Mflash_info;


// ---------------------------------------------------------------------------------------------------------------------
// MUZZLE FLASH FUNCTIONS
//

static const SCP_string mflash_particle_prefix = ";MflashParticle;";

void parse_mflash_tbl(const char *filename)
{
	uint i;

	try
	{
		read_file_text(filename, CF_TYPE_TABLES);
		reset_parse();

		// header
		required_string("#Muzzle flash types");

		while (optional_string("$Mflash:")) {
			mflash_info mflash;
			bool override_mflash = false;

			required_string("+name:");
			stuff_string(mflash.name, F_NAME, MAX_FILENAME_LEN);

			if (optional_string("+override"))
				override_mflash = true;

			// read in all blobs
			while (optional_string("+blob_name:")) {
				mflash_blob_info mblob;

				stuff_string(mblob.name, F_NAME, MAX_FILENAME_LEN);

				required_string("+blob_offset:");
				stuff_float(&mblob.offset);

				required_string("+blob_radius:");
				stuff_float(&mblob.radius);

				mflash.blobs.push_back(mblob);
			}

			for (i = 0; i < Mflash_info.size(); i++) {
				if (!stricmp(mflash.name, Mflash_info[i].name)) {
					if (override_mflash) {
						Mflash_info[i] = mflash;
					}
					break;
				}
			}

			// no matching name exists so add as new
			if (i == Mflash_info.size()) {
				Mflash_info.push_back(mflash);
			}
			// a mflash of the same name exists, don't add it again
			else {
				if (!override_mflash) {
					Warning(LOCATION, "Muzzle flash \"%s\" already exists!  Using existing entry instead.", mflash.name);
				}
			}
		}

		// close
		required_string("#end");
	}
	catch (const parse::ParseException& e)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", filename, e.what()));
		return;
	}
}

static void convert_mflash_to_particle() {
	Curve new_curve = Curve(";MuzzleFlashMinSizeScalingCurve");
	new_curve.keyframes.emplace_back(curve_keyframe{vec2d{ -0.00001f , 0.f}, CurveInterpFunction::Polynomial, -1.0f, 1.0f}); //just for numerical safety if we ever get an actual size of 0...
	new_curve.keyframes.emplace_back(curve_keyframe{vec2d{ Min_pizel_size_muzzleflash, 1.f }, CurveInterpFunction::Constant, 0.0f, 1.0f});
	Curves.emplace_back(std::move(new_curve));
	modular_curves_entry scaling_curve {(static_cast<int>(Curves.size()) - 1), ::util::UniformFloatRange(1.f), ::util::UniformFloatRange(0.f), false};

	for (const auto& mflash : Mflash_info) {
		SCP_vector<particle::ParticleEffect> subparticles;

		for (const auto& blob : mflash.blobs) {
			subparticles.emplace_back(
				mflash_particle_prefix + mflash.name, //Name
				::util::UniformFloatRange(1.f), //Particle num
				particle::ParticleEffect::Duration::ONETIME, //Single Particle Emission
				::util::UniformFloatRange(), //No duration
				::util::UniformFloatRange (-1.f), //Single particle only
				particle::ParticleEffect::ShapeDirection::ALIGNED, //Particle direction
				::util::UniformFloatRange(1.f), //Velocity Inherit
				false, //Velocity Inherit absolute?
				nullptr, //Velocity volume
				::util::UniformFloatRange(), //Velocity volume multiplier
				particle::ParticleEffect::VelocityScaling::NONE, //Velocity directional scaling
				std::nullopt, //Orientation-based velocity
				std::nullopt, //Position-based velocity
				nullptr, //Position volume
				particle::ParticleEffectHandle::invalid(), //Trail
				1.f, //Chance
				false, //Affected by detail
				-1.f, //Culling range multiplier
				false, //Disregard Animation Length. Must be true for everything using particle::Anim_bitmap_X
				false, //Don't reverse animation
				true, //parent local
				true, //ignore velocity inherit if parented
				false, //position velocity inherit absolute?
				std::nullopt, //Local velocity offset
				vec3d{{{0, 0, blob.offset}}}, //Local offset
				::util::UniformFloatRange(-1.f), //Lifetime
				::util::UniformFloatRange(blob.radius), //Radius
				bm_load_animation(blob.name));

			if (Min_pizel_size_muzzleflash > 0) {
				subparticles.back().m_modular_curves.add_curve("Pixel Size At Emitter", particle::ParticleEffect::ParticleCurvesOutput::RADIUS_MULT, scaling_curve);
			}
		}

		particle::ParticleManager::get()->addEffect(std::move(subparticles));
	}

	//Clean up no longer required data
	Mflash_info.clear();
	Mflash_info.shrink_to_fit();
}

// initialize muzzle flash stuff for the whole game
void mflash_game_init()
{
	// parse main table first
	parse_mflash_tbl("mflash.tbl");

	// look for any modular tables
	parse_modular_table(NOX("*-mfl.tbm"), parse_mflash_tbl);

	//This should really happen at parse time, but that requires modular particle effects which aren't yet a thing
	convert_mflash_to_particle();
}

particle::ParticleEffectHandle mflash_lookup(const char *name) {
	return particle::ParticleManager::get()->getEffectByName(mflash_particle_prefix + name);
}