Esempio n. 1
0
PRBool XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, PRUint32 members)
{
    HRESULT hResult;

    XPCDispInterface::Member * pInfo = mMembers;
    mMemberCount = 0;
    for(PRUint32 index = 0; index < members; index++ )
    {
        FUNCDESC* pFuncDesc;
        hResult = pTypeInfo->GetFuncDesc(index, &pFuncDesc );
        if(FAILED(hResult))
            continue;
        if(IsReflectable(pFuncDesc))
        {
            switch(pFuncDesc->invkind)
            {
                case INVOKE_PROPERTYPUT:
                case INVOKE_PROPERTYPUTREF:
                case INVOKE_PROPERTYGET:
                {
                    XPCDispInterface::Member * pExisting = FindExistingMember(mMembers, pInfo, pFuncDesc->memid);
                    if(pExisting == pInfo)
                    {
                        if(InitializeMember(cx, pTypeInfo, pFuncDesc, pInfo))
                        {
                            ++pInfo;
                            ++mMemberCount;
                        }
                    }
                    else
                    {
                        ConvertInvokeKind(pFuncDesc->invkind, *pExisting);
                    }
                    if(pFuncDesc->invkind == INVOKE_PROPERTYGET)
                    {
                        pExisting->SetGetterFuncDesc(pFuncDesc);
                    }
                }
                break;
                case INVOKE_FUNC:
                {
                    if(InitializeMember(cx, pTypeInfo, pFuncDesc, pInfo))
                    {
                        ++pInfo;
                        ++mMemberCount;
                    }
                }
                break;
                default:
                    pTypeInfo->ReleaseFuncDesc(pFuncDesc);
                break;
            }
        }
        else
        {
            pTypeInfo->ReleaseFuncDesc(pFuncDesc);
        }
    }
    return PR_TRUE;
}
Esempio n. 2
0
XPCDispInterface::Allocator::Allocator(JSContext * cx, ITypeInfo * pTypeInfo) :
    mMemIDs(nsnull), mCount(0), mIDispatchMembers(0), mCX(cx), 
    mTypeInfo(pTypeInfo)
{
    TYPEATTR * attr;
    HRESULT hr = pTypeInfo->GetTypeAttr(&attr);
    if(SUCCEEDED(hr))
    {
        mIDispatchMembers = attr->cFuncs;
        mMemIDs = new DISPID[mIDispatchMembers];
        pTypeInfo->ReleaseTypeAttr(attr);
        // Bail if we couldn't create the buffer
        if(!mMemIDs)
            return;
    }
    for(UINT iMethod = 0; iMethod < mIDispatchMembers; iMethod++ )
    {
        FUNCDESC* pFuncDesc;
        if(SUCCEEDED(pTypeInfo->GetFuncDesc(iMethod, &pFuncDesc)))
        {
            // Only add the function to our list if it is at least at nesting level
            // 2 (i.e. defined in an interface derived from IDispatch).
            if(IsReflectable(pFuncDesc))
                Add(pFuncDesc->memid);
            pTypeInfo->ReleaseFuncDesc(pFuncDesc);
        }
    }
}
Esempio n. 3
0
void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, const vec3_t in_dir, vec3_t point, int damage, int dflags, int mod ) {
	gclient_t	*client;
	int			take;
	int			save;
	int			knockback;
	qboolean	wasAlive;
	hitRegion_t	hr = HR_NUM_HITREGIONS;
	int			limbo_health;

	limbo_health = FORCE_LIMBO_HEALTH;

	if (!targ->takedamage) {
		return;
	}

	// the intermission has already been qualified for, so don't
	// allow any extra scoring
	// CHRUKER: b024 - Don't do damage if at warmup and warmupdamage is set to 'None' and the target is a client.
	if ( level.intermissionQueued || (cvars::gameState.ivalue != GS_PLAYING && match_warmupDamage.integer == 0 && targ->client)) {
		return;
	}

	if ( !inflictor ) {
		inflictor = &g_entities[ENTITYNUM_WORLD];
	}
	if ( !attacker ) {
		attacker = &g_entities[ENTITYNUM_WORLD];
	}

	// Arnout: invisible entities can't be damaged
	if( targ->entstate == STATE_INVISIBLE ||
		targ->entstate == STATE_UNDERCONSTRUCTION ) {
		return;
	}

	// xkan, 12/23/2002 - was the bot alive before applying any damage?
	wasAlive = (targ->health > 0) ? qtrue : qfalse;

	// Arnout: combatstate
	if( targ->client && attacker && attacker->client && attacker != targ ) {
		if( cvars::gameState.ivalue == GS_PLAYING ) {
			if( !OnSameTeam( attacker, targ ) ) {
				targ->client->combatState = (combatstate_t)( targ->client->combatState | (1<<COMBATSTATE_DAMAGERECEIVED) );
				attacker->client->combatState = (combatstate_t)( attacker->client->combatState | (1<<COMBATSTATE_DAMAGEDEALT) );
			}
		}
	}

    // JPW NERVE
    if ((targ->waterlevel >= 3) && (mod == MOD_FLAMETHROWER))
        return;
    // jpw

	// shootable doors / buttons don't actually have any health
	if ( targ->s.eType == ET_MOVER && !(targ->isProp) && !targ->scriptName) {
		if ( targ->use && targ->moverState == MOVER_POS1 ) {
			G_UseEntity( targ, inflictor, attacker );
		}
		return;
	}

	// TAT 11/22/2002
	//		In the old code, this check wasn't done for props, so I put that check back in to make props_statue properly work	
	// 4 means destructible
	if ( targ->s.eType == ET_MOVER && (targ->spawnflags & 4) && !targ->isProp ) 
	{
		if( !G_WeaponIsExplosive( (meansOfDeath_t)mod ) ) {
			return;
		}

		// check for team
		if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) {
			return;
		}
	} else if ( targ->s.eType == ET_EXPLOSIVE ) {
		if( targ->parent && G_GetWeaponClassForMOD( (meansOfDeath_t)mod ) == 2 ) {
			return;
		}

		if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) {
			return;
		}

		if( G_GetWeaponClassForMOD( (meansOfDeath_t)mod ) < targ->constructibleStats.weaponclass ) {
			return;
		}
	}
	else if ( targ->s.eType == ET_MISSILE && targ->methodOfDeath == MOD_LANDMINE ) {
		if( targ->s.modelindex2 ) {
			if( G_WeaponIsExplosive( (meansOfDeath_t)mod ) ) {
				mapEntityData_t	*mEnt;

				if((mEnt = G_FindMapEntityData(&mapEntityData[0], targ-g_entities)) != NULL) {
					G_FreeMapEntityData( &mapEntityData[0], mEnt );
				}

				if((mEnt = G_FindMapEntityData(&mapEntityData[1], targ-g_entities)) != NULL) {
					G_FreeMapEntityData( &mapEntityData[1], mEnt );
				}

				if( attacker && attacker->client ) {
					AddScore( attacker, 1 );
				}

				G_ExplodeMissile(targ);
			}
		}
		return;
	} else if ( targ->s.eType == ET_CONSTRUCTIBLE ) {

		if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) {
			return;
		}

		if( G_GetWeaponClassForMOD( (meansOfDeath_t)mod ) < targ->constructibleStats.weaponclass ) {
			return;
		}
		//bani - fix #238
		if ( mod == MOD_DYNAMITE ) {
			if( !( inflictor->etpro_misc_1 & 1 ) )
				return;
		}
	}

	client = targ->client;

	if ( client ) {
		if ( client->noclip || ( client->ps.powerups[PW_INVULNERABLE] && !( dflags & DAMAGE_JAY_NO_PROTECTION ))) {
			return;
		}
	}

	// check for godmode
	if ( targ->flags & FL_GODMODE ) {
		return;
	}

    // ugly-ass code but we do this to make in_dir read-only
    vec3_t dir;

	if ( !in_dir ) {
		dflags |= DAMAGE_NO_KNOCKBACK;
	} else {
        VectorCopy( in_dir, dir );
		VectorNormalize( dir );
	}

	knockback = damage;
	if ( knockback > 200 ) {
		knockback = 200;
	}
	if ( targ->flags & FL_NO_KNOCKBACK ) {
		knockback = 0;
	}
	if ( dflags & DAMAGE_NO_KNOCKBACK ) {
		knockback = 0;
	} else if( dflags & DAMAGE_HALF_KNOCKBACK ) {
		knockback = int( knockback * 0.5f );
	}
	
	// ydnar: set weapons means less knockback
	if( client && (client->ps.weapon == WP_MORTAR_SET || client->ps.weapon == WP_MOBILE_MG42_SET) )
		knockback = int( knockback * 0.5f );

	if( targ->client && g_friendlyFire.integer && OnSameTeam(targ, attacker) ) {
		knockback = 0;
	}
	
	// figure momentum add, even if the damage won't be taken
	if ( knockback && targ->client ) {
		vec3_t	kvel;
		float	mass;

		mass = 200;

		VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
		VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);

        // From NoQuarter, I'm not sure I need this
		if ( attacker && attacker->client && ( targ->client->ps.groundEntityNum != ENTITYNUM_NONE || G_WeaponIsExplosive((meansOfDeath_t)mod) )){
			targ->client->pmext.wasShoved = qtrue;
			targ->client->pmext.shover = attacker - g_entities;
		}

		if (targ == attacker && !(	mod != MOD_ROCKET &&
									mod != MOD_GRENADE &&
									mod != MOD_GRENADE_LAUNCHER &&
									mod != MOD_DYNAMITE
									&& mod != MOD_GPG40
									&& mod != MOD_M7
									&& mod != MOD_LANDMINE
									))
		{
			targ->client->ps.velocity[2] *= 0.25;
		}

		// set the timer so that the other client can't cancel
		// out the movement immediately
		if ( !targ->client->ps.pm_time ) {
			int		t;

			t = knockback * 2;
			if ( t < 50 ) {
				t = 50;
			}
			if ( t > 200 ) {
				t = 200;
			}
			targ->client->ps.pm_time = t;
			targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		}
	}

    // skip damage if friendly fire is disabled
    if (!(dflags & DAMAGE_NO_PROTECTION)
        && targ != attacker
        && OnSameTeam( targ, attacker )
        && !g_friendlyFire.integer)
    {
        return;
    }

	if (damage < 1)
		damage = 1;

	take = damage;
	save = 0;

	if ( attacker->client && targ->client && targ != attacker && targ->health > 0 ) {
		// Jaybird - Hitsounds
		// vsay "hold your fire" on the first hit of a teammate
		// only applies if the player has been hurt before
		// and the match is not in warmup.
		if( OnSameTeam( targ, attacker )) {
			if(( !client->lasthurt_mod || client->lasthurt_client != attacker->s.number ) && cvars::gameState.ivalue == GS_PLAYING && ( targ->health - take ) > limbo_health ) {
				if( client->sess.sessionTeam == TEAM_AXIS )
					G_ClientSound( attacker, "sound/chat/axis/26a.wav" );
				else	
					G_ClientSound( attacker, "sound/chat/allies/26a.wav" );
			}

			if (mod != MOD_GOOMBA && mod != MOD_POISON_SYRINGE) {
				g_clientObjects[attacker->s.number].recordHit( AbstractHitVolume::ZONE_BODY, true );
			}
		} else {
			if (mod != MOD_GOOMBA && mod != MOD_POISON_SYRINGE) {
				g_clientObjects[attacker->s.number].recordHit( AbstractHitVolume::ZONE_BODY, false );
			}
		}
	}

	// adrenaline junkie!
	if( targ->client && targ->client->ps.powerups[PW_ADRENALINE] ) {
		take = int( take * 0.5f );
	}

	// save some from flak jacket
	// Jaybird - engineer class carryover
	if( targ->client && targ->client->sess.skill[SK_EXPLOSIVES_AND_CONSTRUCTION] >= 4 && ( targ->client->sess.playerType == PC_ENGINEER || ( cvars::bg_skills.ivalue & SBS_ENGI ))) {
		if( mod == MOD_GRENADE ||
			mod == MOD_GRENADE_LAUNCHER ||
			mod == MOD_ROCKET ||
			mod == MOD_GRENADE_PINEAPPLE ||
			mod == MOD_MAPMORTAR ||
			mod == MOD_MAPMORTAR_SPLASH || 
			mod == MOD_EXPLOSIVE ||
			mod == MOD_LANDMINE ||
			mod == MOD_GPG40 ||
			mod == MOD_M7 ||
			mod == MOD_SATCHEL ||
			mod == MOD_ARTY ||
			mod == MOD_AIRSTRIKE ||
			mod == MOD_DYNAMITE ||
			mod == MOD_MORTAR ||
			mod == MOD_PANZERFAUST ||
			mod == MOD_MAPMORTAR ) {
			take -= int( take * 0.5f );
		}
	}

#ifndef DEBUG_STATS
	if ( g_debugDamage.integer )
#endif
	{
		G_Printf( "client:%i health:%i damage:%i mod:%s\n", targ->s.number, targ->health, take, modNames[mod] );
	}

	if( targ && targ->client && attacker && attacker->client && targ != attacker && targ->health > 0 && OnSameTeam( targ, attacker ) && g_friendlyFire.integer == 2 && IsReflectable( mod )) {
		int ffDamage;

		// Percentage based reflect
		ffDamage = int( take * g_reflectFriendlyFire.value / 100.f );
		if( ffDamage <= 0 ) {
			ffDamage = 0;
		}
		attacker->health -= ffDamage;

		// Give them pain!
		attacker->client->damage_blood += take;
		attacker->client->damage_knockback += knockback;

		// Set the lasthurt stuff so hitsounds do not replay
		targ->client->lasthurt_mod = mod;
		targ->client->lasthurt_client = attacker - g_entities;

		// Kill the player if necessary
		if( attacker->health <= 0 ) {
			attacker->deathType = MOD_REFLECTED_FF;
			attacker->enemy = attacker;
			if( attacker->die ) {
				attacker->die( attacker, attacker, attacker, ffDamage, MOD_REFLECTED_FF );
			}
		}
	}

	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks
	// at the end of the frame
	if ( client ) {
		if ( attacker ) {
			client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
		} else {
			client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
		}
		client->damage_blood += take;
		client->damage_knockback += knockback;

		if ( dir ) {
			VectorCopy ( dir, client->damage_from );
			client->damage_fromWorld = qfalse;
		} else {
			VectorCopy ( targ->r.currentOrigin, client->damage_from );
			client->damage_fromWorld = qtrue;
		}
	}

	// See if it's the player hurting the emeny flag carrier
//	Team_CheckHurtCarrier(targ, attacker);

	if (targ->client) {
		// set the last client who damaged the target
		targ->client->lasthurt_client = attacker->s.number;
		targ->client->lasthurt_mod = mod;
		targ->client->lasthurt_time = level.time;
	}

	// do the damage
	if( take ) {
		targ->health -= take;

		// Gordon: don't ever gib POWS
		if( ( targ->health <= 0 ) && ( targ->r.svFlags & SVF_POW ) ) {
			targ->health = -1;
		}

		// Ridah, can't gib with bullet weapons (except VENOM)
		// Arnout: attacker == inflictor can happen in other cases as well! (movers trying to gib things)
		//if ( attacker == inflictor && targ->health <= GIB_HEALTH) {
		if( targ->health <= GIB_HEALTH ) {
			if( !G_WeaponIsExplosive( (meansOfDeath_t)mod ) ) {
				targ->health = GIB_HEALTH + 1;
			}
		}

		if( g_damagexp.integer && client && G_GetTeamFromEntity( inflictor ) != G_GetTeamFromEntity( targ )) {
			// Jaybird - give them some per hit
			// They get 1 XP per 50 damage, so multiple .02 * take
			int skill = G_SkillForMOD( mod );
			if( skill >= 0 )
				G_AddSkillPoints( attacker, (skillType_t)skill, take * .02 );
		}

// JPW NERVE overcome previous chunk of code for making grenades work again
//		if ((take > 190)) // 190 is greater than 2x mauser headshot, so headshots don't gib
		// Arnout: only player entities! messes up ents like func_constructibles and func_explosives otherwise
		if( ( (targ->s.number < MAX_CLIENTS) && (take > 190) ) && !(targ->r.svFlags & SVF_POW) ) {
			targ->health = GIB_HEALTH - 1;
		}

		if( targ->s.eType == ET_MOVER && !Q_stricmp( targ->classname, "script_mover" ) ) {
			targ->s.dl_intensity = int( 255.f * (targ->health / (float)targ->count) );	// send it to the client
		}

		//G_Printf("health at: %d\n", targ->health);
		if( targ->health <= 0 ) {
			if( client && !wasAlive ) {
				targ->flags |= FL_NO_KNOCKBACK;
				// OSP - special hack to not count attempts for body gibbage
				if( targ->client->ps.pm_type == PM_DEAD ) {
					G_addStats(targ, attacker, take, mod);
				}

				if( (targ->health < FORCE_LIMBO_HEALTH) && (targ->health > GIB_HEALTH) ) {
					limbo(targ, qtrue);
				}
				// xkan, 1/13/2003 - record the time we died.
				if (!client->deathTime)
					client->deathTime = level.time;

				//bani - #389
				if( targ->health <= GIB_HEALTH ) {
					GibEntity( targ, 0 );
				}
			} else {
				targ->sound1to2 = hr;
				targ->sound2to1 = mod;
				targ->sound2to3 = (dflags & DAMAGE_RADIUS) ? 1 : 0;

				if( client ) {
					if( G_GetTeamFromEntity( inflictor ) != G_GetTeamFromEntity( targ ) ) {
						G_AddKillSkillPoints( attacker, (meansOfDeath_t)mod, hr, (qboolean)(dflags & DAMAGE_RADIUS)  );
					}
				}

				if( targ->health < -999 ) {
					targ->health = -999;
				}


				targ->enemy = attacker;
				targ->deathType = (meansOfDeath_t)mod;

				// Ridah, mg42 doesn't have die func (FIXME)
				if( targ->die ) {	
					// Kill the entity.  Note that this funtion can set ->die to another
					// function pointer, so that next time die is applied to the dead body.
					targ->die( targ, inflictor, attacker, take, mod );
					// OSP - kill stats in player_die function
				}

				if( targ->s.eType == ET_MOVER && !Q_stricmp( targ->classname, "script_mover" ) && (targ->spawnflags & 8) ) {
					return;	// reseructable script mover doesn't unlink itself but we don't want a second death script to be called
				}

				// if we freed ourselves in death function
				if (!targ->inuse)
					return;

				// RF, entity scripting
				if ( targ->health <= 0) {	// might have revived itself in death function
					if( targ->r.svFlags & SVF_BOT ) {
                        // Removed
					} else if(	( targ->s.eType != ET_CONSTRUCTIBLE && targ->s.eType != ET_EXPLOSIVE ) ||
								( targ->s.eType == ET_CONSTRUCTIBLE && !targ->desstages ) )	{ // call manually if using desstages
						G_Script_ScriptEvent( targ, "death", "" );
					}
				}
			}

		} else if ( targ->pain ) {
			if (dir) {	// Ridah, had to add this to fix NULL dir crash
				VectorCopy (dir, targ->rotate);
				VectorCopy (point, targ->pos3); // this will pass loc of hit
			} else {
				VectorClear( targ->rotate );
				VectorClear( targ->pos3 );
			}

			targ->pain (targ, attacker, take, point);
		} else {
			// OSP - update weapon/dmg stats
			G_addStats(targ, attacker, take, mod);
			// OSP
		}

		// RF, entity scripting
		G_Script_ScriptEvent( targ, "pain", va("%d %d", targ->health, targ->health+take) );

		// RF, record bot pain
		if (targ->s.number < level.maxclients)
		{
			// notify omni-bot framework
			Bot_Event_TakeDamage(targ-g_entities, attacker);
		}

		// Ridah, this needs to be done last, incase the health is altered in one of the event calls
		// Jaybird - playdead check
		if ( targ->client ) {
			targ->client->ps.stats[STAT_HEALTH] = targ->health;
		}

        // Cheap way to ID inflictor entity as poison smoke.
		if (inflictor->poisonGasAlarm && mod == MOD_POISON_GAS && targ->health >= 0)
			G_AddEvent(targ, EV_COUGH, 0);
	}
}