mse / RSOD (public) (License: CC0 and other licenses) (since 2025-03-01) (hash sha1)
Free software FPS engine
List of commits:
Subject Hash Author Date (UTC)
Add support for particle damage/impact ed57530ab69e9c32ac19c0c6a36cb6102791b7c6 MSE 2024-06-12 00:25:18
Add agent linear velocity to projectiles 2e254d93065e60a6e76dab321aa64aaad72dede7 MSE 2024-06-11 16:34:15
Add weapon particle support dc972a7f2cc0019d663b3284a1e49c3be313c74f MSE 2024-06-09 20:21:23
Initial commit c4f36c095752bd4e7090caf48320d041fb2328bb MSE 2024-06-09 02:33:29
Commit ed57530ab69e9c32ac19c0c6a36cb6102791b7c6 - Add support for particle damage/impact
Author: MSE
Author date (UTC): 2024-06-12 00:25
Committer name: MSE
Committer date (UTC): 2024-06-12 00:25
Parent(s): 2e254d93065e60a6e76dab321aa64aaad72dede7
Signer:
Signing key:
Signing status: N
Tree: a47ce7581d3238f1a749cec85390c18709da4a29
File Lines added Lines deleted
include/particle.h 22 4
src/fdungeon.cpp 26 6
src/rsod.cpp 1 1
File include/particle.h changed (mode: 100644) (index 85cae5e..d3a7c1a)
... ... class Particle {
28 28 double dragModel = 0.525; // A cube. double dragModel = 0.525; // A cube.
29 29 double age = 0.0; double age = 0.0;
30 30 double maxAge = DBL_MAX; double maxAge = DBL_MAX;
31 double damage = 0.0; // Damage dealt on impact. User should test collisions if nonzero.
32 void *userptr = nullptr; // Not loaded from JSON. User can set this.
31 33 }; };
32 34
33 35 class ParticleTemplate { class ParticleTemplate {
 
... ... class ParticleTemplate {
40 42 double startMass = 1.0; double startMass = 1.0;
41 43 double endMass = 1.0; double endMass = 1.0;
42 44 double maxAge = DBL_MAX; double maxAge = DBL_MAX;
45 double damage = 0.0;
43 46 ParticleTemplate( const std::string &text = "" ); ParticleTemplate( const std::string &text = "" );
44 47 }; };
45 48
 
... ... class ParticleServer {
60 63 double endScale, double endScale,
61 64 double startMass, double startMass,
62 65 double endMass, double endMass,
63 double maxAge );
66 double maxAge,
67 double damage,
68 void *userptr = nullptr );
64 69 void addOmniBurst( void addOmniBurst(
65 70 size_t num, size_t num,
66 71 double vel, double vel,
 
... ... class ParticleServer {
69 74 double endScale, double endScale,
70 75 double startMass, double startMass,
71 76 double endMass, double endMass,
72 double maxAge );
77 double maxAge,
78 double damage,
79 void *userptr = nullptr );
73 80 void simulate( double d ); void simulate( double d );
74 81 void draw( fgl::Texture &tex, linalg::mat<double,4,4> viewMat, linalg::mat<double,4,4> projMat, bool shadowPass = false ); void draw( fgl::Texture &tex, linalg::mat<double,4,4> viewMat, linalg::mat<double,4,4> projMat, bool shadowPass = false );
75 82 ParticleServer(); ParticleServer();
 
... ... ParticleTemplate::ParticleTemplate( const std::string &text ){
122 129 if( info["maxAge"] ){ if( info["maxAge"] ){
123 130 maxAge = info["maxAge"].getDouble(); maxAge = info["maxAge"].getDouble();
124 131 } }
132 if( info["damage"] ){
133 damage = info["damage"].getDouble();
134 }
125 135
126 136 jsonFreeDocument( &allocatedDocument ); jsonFreeDocument( &allocatedDocument );
127 137 } }
 
... ... void ParticleServer::addParticle(
143 153 double endScale, double endScale,
144 154 double startMass, double startMass,
145 155 double endMass, double endMass,
146 double maxAge ){
156 double maxAge,
157 double damage,
158 void *userptr ){
147 159 Particle part{}; Particle part{};
148 160 part.tvel = vel; part.tvel = vel;
149 161 part.translation = pos; part.translation = pos;
 
... ... void ParticleServer::addParticle(
152 164 part.mvel = (endMass - startMass) / maxAge; part.mvel = (endMass - startMass) / maxAge;
153 165 part.mass = startMass; part.mass = startMass;
154 166 part.maxAge = maxAge; part.maxAge = maxAge;
167 part.damage = damage;
168 part.userptr = userptr;
155 169 particles.push_back( part ); particles.push_back( part );
156 170 } }
157 171
 
... ... void ParticleServer::addOmniBurst(
163 177 double endScale, double endScale,
164 178 double startMass, double startMass,
165 179 double endMass, double endMass,
166 double maxAge ){
180 double maxAge,
181 double damage,
182 void *userptr ){
167 183 double svel = (endScale - startScale) / maxAge; double svel = (endScale - startScale) / maxAge;
168 184 double mvel = (endMass - startMass) / maxAge; double mvel = (endMass - startMass) / maxAge;
169 185 for( size_t i = 0; i < num; ++i ){ for( size_t i = 0; i < num; ++i ){
 
... ... void ParticleServer::addOmniBurst(
178 194 part.mvel = mvel; part.mvel = mvel;
179 195 part.mass = startMass; part.mass = startMass;
180 196 part.maxAge = maxAge; part.maxAge = maxAge;
197 part.damage = damage;
198 part.userptr = userptr;
181 199 particles.push_back( part ); particles.push_back( part );
182 200 } }
183 201 } }
File src/fdungeon.cpp changed (mode: 100644) (index c0b2e91..05186db)
... ... class Dungeon {
502 502 void moveMouse( double x, double y ); void moveMouse( double x, double y );
503 503 void prepareLightBuffers( double d ); void prepareLightBuffers( double d );
504 504 void simulateWater( float wscale, double d ); void simulateWater( float wscale, double d );
505 void simulate( double maxDraw, double d );
505 void simulate( double maxDraw, double d, std::string defenseSkill = "def" );
506 506 void updateMonoCamera(); void updateMonoCamera();
507 507 void updateStereoCamera(); void updateStereoCamera();
508 508 fgl::Pipeline useDungeonPipeline( bool skinPass, bool shadowPass ); fgl::Pipeline useDungeonPipeline( bool skinPass, bool shadowPass );
 
... ... Agent *Dungeon::rayImpact( Agent *a, std::pair<linalg::vec<double,3>,linalg::vec
3229 3229 defaultBlood.num, defaultBlood.vel, defaultBlood.num, defaultBlood.vel,
3230 3230 {hit.getX(), hit.getY(), hit.getZ()}, {hit.getX(), hit.getY(), hit.getZ()},
3231 3231 defaultBlood.startScale, defaultBlood.endScale, defaultBlood.startScale, defaultBlood.endScale,
3232 defaultBlood.startMass, defaultBlood.endMass, defaultBlood.maxAge );
3232 defaultBlood.startMass, defaultBlood.endMass, defaultBlood.maxAge,
3233 defaultBlood.damage, (void*)&defaultAgent );
3233 3234 } }
3234 3235 }else{ }else{
3235 3236 // No avatar = default impact // No avatar = default impact
 
... ... Agent *Dungeon::rayImpact( Agent *a, std::pair<linalg::vec<double,3>,linalg::vec
3239 3240 defaultImpact.num, defaultImpact.vel, defaultImpact.num, defaultImpact.vel,
3240 3241 {hit.getX(), hit.getY(), hit.getZ()}, {hit.getX(), hit.getY(), hit.getZ()},
3241 3242 defaultImpact.startScale, defaultImpact.endScale, defaultImpact.startScale, defaultImpact.endScale,
3242 defaultImpact.startMass, defaultImpact.endMass, defaultImpact.maxAge );
3243 defaultImpact.startMass, defaultImpact.endMass, defaultImpact.maxAge,
3244 defaultImpact.damage, (void*)&defaultAgent );
3243 3245 } }
3244 3246 } }
3245 3247 }else{ }else{
 
... ... Agent *Dungeon::rayImpact( Agent *a, std::pair<linalg::vec<double,3>,linalg::vec
3254 3256 defaultImpact.num, defaultImpact.vel, defaultImpact.num, defaultImpact.vel,
3255 3257 {hit.getX(), hit.getY(), hit.getZ()}, {hit.getX(), hit.getY(), hit.getZ()},
3256 3258 defaultImpact.startScale, defaultImpact.endScale, defaultImpact.startScale, defaultImpact.endScale,
3257 defaultImpact.startMass, defaultImpact.endMass, defaultImpact.maxAge );
3259 defaultImpact.startMass, defaultImpact.endMass, defaultImpact.maxAge,
3260 defaultImpact.damage, (void*)&defaultAgent );
3258 3261 } }
3259 3262 } }
3260 3263 if( rb->getInvMass() != 0.0 ){ if( rb->getInvMass() != 0.0 ){
 
... ... std::pair<bool,Agent*> Dungeon::agentFireWeapon( Agent *a, std::string weapon, s
3352 3355 part.mvel = mvel; part.mvel = mvel;
3353 3356 part.mass = startMass; part.mass = startMass;
3354 3357 part.maxAge = maxAge; part.maxAge = maxAge;
3358 part.damage = weap.particleFire.damage;
3359 part.userptr = (void*)a;
3355 3360 ps_it->second.particles.push_back(part); ps_it->second.particles.push_back(part);
3356 3361 } }
3357 3362 } }
 
... ... template<class T> linalg::mat<T,4,4> ortho(
3770 3775 } }
3771 3776
3772 3777 // Physics, shadow, and camera position handling. // Physics, shadow, and camera position handling.
3773 void Dungeon::simulate( double maxDraw, double d ){
3778 void Dungeon::simulate( double maxDraw, double d, std::string defenseSkill ){
3774 3779 if( !dynamicsWorld ) if( !dynamicsWorld )
3775 3780 return; return;
3776 3781 simulateWater( 16.0f, d ); simulateWater( 16.0f, d );
 
... ... void Dungeon::simulate( double maxDraw, double d ){
3996 4001 } }
3997 4002
3998 4003 // Simulate particles. // Simulate particles.
3999 for( auto &ps : particleServers ) ps.second.simulate( d );
4004 for( auto &ps : particleServers ){
4005 ps.second.simulate( d );
4006 // Simulate collisions and damage for damaging particles.
4007 for( auto &p : ps.second.particles ){
4008 if( p.damage != 0.0 ){
4009 // Cast a ray from the particle's previous position to its current position.
4010 // Cap mass to 10 kg because it may be set very high in order to cheat drag.
4011 // Ultra-high mass = ultra-high impact = objects clip through walls
4012 auto tprev = p.translation - p.tvel * d;
4013 if(rayImpact((Agent*)p.userptr, {tprev, p.translation},
4014 linalg::length(p.tvel) * std::min(p.mass, 10.0), p.damage, defenseSkill)){
4015 p.age = DBL_MAX;
4016 }
4017 }
4018 }
4019 }
4000 4020
4001 4021 // Configure the shadow map. // Configure the shadow map.
4002 4022 //shadowViewMat = linalg::pose_matrix( fgl::eulerToQuat( -0.7, 0.0, 0.0 ), { 0.0, 10.0, 20.0 } ); //shadowViewMat = linalg::pose_matrix( fgl::eulerToQuat( -0.7, 0.0, 0.0 ), { 0.0, 10.0, 20.0 } );
File src/rsod.cpp changed (mode: 100644) (index 84da87e..e189e4e)
... ... bool aiFrame( fdungeon::Agent *a, double d ){
1583 1583 100, 100,
1584 1584 15.0, 15.0,
1585 1585 {o.getX(), o.getY(), o.getZ()}, {o.getX(), o.getY(), o.getZ()},
1586 0.5, 0.1, 0.01, 0.001, 6.0 );
1586 0.5, 0.1, 0.01, 0.001, 6.0, 0.0 );
1587 1587 } }
1588 1588 csPlaySound( a->soundExplode, false ); csPlaySound( a->soundExplode, false );
1589 1589 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/mse/RSOD

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/mse/RSOD

Clone this repository using git:
git clone git://git.rocketgit.com/user/mse/RSOD

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main