1. After extensive testing, I have determined that all non-model weapons (i.e., those that do not have a hitsphere of their own) are still not impacting on targets appropriately, and simply do not exhibit proper hit detection. I do not know whether this is because these weapons have an associated model or not, but I now strongly suspect this is the case, after performing additional tests.
This is a bug from 0.72b, and in 0.73b, it's still present and unfixed. This is a very serious bug, from a gameplay standpoint. Laser weapons are utterly useless against fast-moving or small targets and seemingly-solid beams often pass through smaller objects' hitspheres entirely... without generating a hit.
I don't know what causes this bug, but it has something to with the hitscan code, which apparantly treats these weapons as if they're points that are very tiny. I have a feeling there's a rounding bug or something simple like that going on, because these weapons work just fine on larger or slow-moving targets- just not small, fast ones.
If you want to see me actually use the majority of my fancy laser/plasma/etc. FX things that I'm building for the GPL version of NanoBlobs (and obviously would like to give to Spring's community)... erm, please fix this, it's probably just a teeny thing, with big consequences

I'm not sure where this going wrong. I've looked at the rts\Sim\Misc\QuadField.cpp hitscan code, and I'm confused.
This section, if I had to guess, looks like it's the one being used for laser beams and other point objects:
Code: Select all
vector<int> CQuadField::GetQuadsOnRay(float3 start, float3 dir, float length)
{
vector<int> quads;
if(start.x<1){
if(dir.x==0)
dir.x=0.00001;
start=start+dir*((1-start.x)/dir.x);
}
if(start.x>gs->mapx*SQUARE_SIZE-1){
if(dir.x==0)
dir.x=0.00001;
start=start+dir*((gs->mapx*SQUARE_SIZE-1-start.x)/dir.x);
}
if(start.z<1){
if(dir.z==0)
dir.z=0.00001;
start=start+dir*((1-start.z)/dir.z);
}
if(start.z>gs->mapy*SQUARE_SIZE-1){
if(dir.z==0)
dir.z=0.00001;
start=start+dir*((gs->mapy*SQUARE_SIZE-1-start.z)/dir.z);
}
if(start.x<1){
start.x=1;
}
if(start.x>gs->mapx*SQUARE_SIZE-1){
start.x=gs->mapx*SQUARE_SIZE-1;
}
if(start.z<1){
start.z=1;
}
if(start.z>gs->mapy*SQUARE_SIZE-1){
start.z=gs->mapy*SQUARE_SIZE-1;
}
float3 to=start+dir*length;
if(to.x<1){
to=to-dir*((to.x-1)/dir.x);
}
if(to.x>gs->mapx*SQUARE_SIZE-1){
to=to-dir*((to.x-gs->mapx*SQUARE_SIZE+1)/dir.x);
}
if(to.z<1){
to=to-dir*((to.z-1)/dir.z);
}
if(to.z>gs->mapy*SQUARE_SIZE-1){
to=to-dir*((to.z-gs->mapy*SQUARE_SIZE+1)/dir.z);
}
//these 4 shouldnt be needed but sometimes we seem to get strange enough values that rounding errors throw us outide the map
if(to.x<1){
to.x=1;
}
if(to.x>gs->mapx*SQUARE_SIZE-1){
to.x=gs->mapx*SQUARE_SIZE-1;
}
if(to.z<1){
to.z=1;
}
if(to.z>gs->mapy*SQUARE_SIZE-1){
to.z=gs->mapy*SQUARE_SIZE-1;
}
// if(to.x<0){
/// info->AddLine("error %f %f %f %f %f %f %f %f",start.x,start.z,to.x,to.z,dir.x,dir.z,dir.y,length);
// }
float dx=to.x-start.x;
float dz=to.z-start.z;
float xp=start.x;
float zp=start.z;
float xn,zn;
float invQuadSize=1.0/QUAD_SIZE;
if((floor(start.x*invQuadSize)==floor(to.x*invQuadSize)) && (floor(start.z*invQuadSize)==floor(to.z*invQuadSize))){
quads.push_back((int(start.x*invQuadSize))+(int(start.z*invQuadSize))*numQuadsX);
} else if(floor(start.x*invQuadSize)==floor(to.x*invQuadSize)){
int first=(int(start.x*invQuadSize))+(int(start.z*invQuadSize))*numQuadsX;
int last=(int(to.x*invQuadSize))+(int(to.z*invQuadSize))*numQuadsX;
if(dz>0)
for(int a=first;a<=last;a+=numQuadsX)
quads.push_back(a);
else
for(int a=first;a>=last;a-=numQuadsX)
quads.push_back(a);
} else if(floor(start.z*invQuadSize)==floor(to.z*invQuadSize)){
int first=(int(start.x*invQuadSize))+(int(start.z*invQuadSize))*numQuadsX;
int last=(int(to.x*invQuadSize))+(int(to.z*invQuadSize))*numQuadsX;
if(dx>0)
for(int a=first;a<=last;a++)
quads.push_back(a);
else
for(int a=first;a>=last;a--)
quads.push_back(a);
} else {
bool keepgoing=true;
while(keepgoing){
quads.push_back((int(zp*invQuadSize))*numQuadsX+(int(xp*invQuadSize)));
if(dx>0){
xn=(floor(xp*invQuadSize)*QUAD_SIZE+QUAD_SIZE-xp)/dx;
} else {
xn=(floor(xp*invQuadSize)*QUAD_SIZE-xp)/dx;
}
if(dz>0){
zn=(floor(zp*invQuadSize)*QUAD_SIZE+QUAD_SIZE-zp)/dz;
} else {
zn=(floor(zp*invQuadSize)*QUAD_SIZE-zp)/dz;
}
if(xn<zn){
xp+=(xn+0.0001)*dx;
zp+=(xn+0.0001)*dz;
} else {
xp+=(zn+0.0001)*dx;
zp+=(zn+0.0001)*dz;
}
keepgoing=fabs(xp-start.x)<fabs(to.x-start.x) && fabs(zp-start.z)<fabs(to.z-start.z);
}
}
return quads;
}
If I'm reading that code right, it uses a ridiculously low value XYZ for the size of these objects. This may be causing it to round to zero on later steps. I dunno... I'm not really sure if this is even the right code.
This sections below states it's for "projectile collisions". Does that mean nuke/antinuke, or for weapons in general, or... what? If anybody can point me to the code that actually handles BeamWeapon/BeamLaser collisions with objects, so I'm not just groping around here, I'll take a longer look at this... as I said, though, this is probably a very quick fix.
Code: Select all
// optimization specifically for projectile collisions
void CQuadField::GetUnitsAndFeaturesExact(const float3& pos, float radius, const vector<int>& quads, vector<CUnit*>& dstunits, vector<CFeature*>& dstfeatures)
{
int tempNum=gs->tempNum++;
vector<int>::const_iterator qi;
for(qi=quads.begin();qi!=quads.end();++qi){
list<CUnit*>::iterator ui;
for(ui=baseQuads[*qi].units.begin();ui!=baseQuads[*qi].units.end();++ui){
if((*ui)->tempNum!=tempNum){
(*ui)->tempNum=tempNum;
dstunits.push_back(*ui);
}
}
}
for(qi=quads.begin();qi!=quads.end();++qi){
list<CFeature*>::iterator fi;
for(fi=baseQuads[*qi].features.begin();fi!=baseQuads[*qi].features.end();++fi){
float totRad=radius+(*fi)->radius;
if((*fi)->tempNum!=tempNum && (pos-(*fi)->midPos).SqLength()<totRad*totRad){
(*fi)->tempNum=tempNum;
dstfeatures.push_back(*fi);
}
}
}
}
2. I have yet to get LargeBeamWeapon working as advertised. Anybody have working code yet? I'd like to figure that out, and compare it to my other concepts I'm working with. I'm not going to give it away yet, but I've come up with something that's very, very exciting... and very probably... just as good-looking.
3. I have found that if one doesn't use powers of 64 on the bitmaps, then artefacts tend to appear when the texture squares / rectangles are being rendered

4. I've tried ExplosionSpeed out... and it needs to be made clear in the documentation that this is a multiplier. Making it gigantic isn't necessary- even a value of as little as 10 makes most explosions effectively instant. What I'd like, and what I'm having trouble achieving... is to have an explosion that is very non-instant- I was kind've hoping to fix the Demon's gun so that it's no longer a crude hack-around, but is a true area-denial weapon. However, this isn't working very well at this time.
5. I already noted the whole ImpulseFactor bug in a previous thread, but I'm noting it again here- it's definately a bug.
When the following are all zero, a weapon should never impart ImpulseFactor, cause craters, etc.:
Code: Select all
impulsefactor=0;
impulseBoost=0;
craterMult=0;
craterBoost=0;
Some good things I should note here:
1. I've tested the new LOS code, and it's very useful, and works as advertised. I see very little degradation of LOS results with 2X, even with land units. Should be very useful for people wanting to test out long LOS mods.
2. The FX I have gotten working properly thus far are... just gorgeous. Period. I cannot wait to get them all working right!
3. I've noticed that water now reflects all weapons properly.[/code]