Пример #1
0
void magmine_attack(edict_t *self) {
    int pull;
    vec3_t start, end, dir;

    // magmine will not pull a target that is below it
    // this prevents players from placing magmines to pull a target off their feet
    if (self->enemy->absmin[2] + 1 < self->absmin[2])
        return;

    G_EntMidPoint(self->enemy, end);
    G_EntMidPoint(self, start);
    VectorSubtract(end, start, dir);
    VectorNormalize(dir);

    pull = MAGMINE_DEFAULT_PULL + MAGMINE_ADDON_PULL * self->monsterinfo.level;
    if (self->enemy->groundentity)
        pull *= 2;

    // pull them in!
    T_Damage(self->enemy, self, self, dir, end, vec3_origin, 0, pull, 0, 0);

    if (level.time > self->delay) {
        gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/tlaser.wav"), 1, ATTN_IDLE, 0);
        self->delay = level.time + 2;
    }
}
Пример #2
0
void mybrain_suxor (edict_t *self)
{
	int		damage, range, pull;
	vec3_t	start, v, end;
	trace_t	tr;

	if (!self->enemy)
		return;
	if (!self->enemy->inuse)
		return;

	self->lastsound = level.framenum;

	G_EntMidPoint(self->enemy, start);
	VectorSubtract(start, self->s.origin, v);
	self->ideal_yaw = vectoyaw(v);
	M_ChangeYaw (self);
	range = VectorLength(v);
	VectorNormalize(v);
	VectorMA(self->s.origin, 512, v, end);
	tr = gi.trace(self->s.origin, NULL, NULL, end, self, MASK_SHOT);
	if (G_EntExists(tr.ent) && (tr.ent == self->enemy))
	{
		damage = BRAIN_INITIAL_TENTACLE_DMG + BRAIN_ADDON_TENTACLE_DMG*self->monsterinfo.level;
		pull = BRAIN_INITIAL_PULL + BRAIN_ADDON_PULL*self->monsterinfo.level;

		if (tr.ent->groundentity)
			pull *= 2;

		if (range > 64)
			T_Damage(tr.ent, self, self, v, tr.endpos, tr.plane.normal, 0, pull, 0, MOD_UNKNOWN);
		else
			T_Damage(tr.ent, self, self, v, tr.endpos, tr.plane.normal, damage, pull, 0, MOD_UNKNOWN);
	}
}
Пример #3
0
void mymedic_cable_attack (edict_t *self)
{
	vec3_t	forward, right, start, offset, end;
	trace_t	tr;

	// need a valid target and activator
	if (!self || !self->inuse || !self->activator || !self->activator->inuse 
		|| !self->enemy || !self->enemy->inuse)
		return;

	// make sure target is still in range
	if (entdist(self, self->enemy) > 256)
		return;

	// get muzzle location
	AngleVectors(self->s.angles, forward, right, NULL);
	VectorCopy(mymedic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource(self->s.origin, offset, forward, right, start);
	// get end position
	//VectorCopy(self->enemy->s.origin, end);
	//end[2] = self->enemy->absmax[2]-8;
	G_EntMidPoint(self->enemy, end);

	tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT);
	if (tr.ent != self->enemy)
		return; // cable is blocked

	// cable effect
	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort (self - g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (tr.endpos);
	gi.multicast (self->s.origin, MULTICAST_PVS);

	// the target needs healing
	if (M_NeedRegen(self->enemy))
	{
		int frames = 6000/(12*self->monsterinfo.level);

		if (!frames)
			frames = 1;

		// remove all curses
		CurseRemove(self->enemy, 0);

		//Give them a short period of curse immunity
		self->enemy->holywaterProtection = level.time + 2.0; //2 seconds immunity

		// heal them
		M_Regenerate(self->enemy, frames, 0, 1.0, true, true, false, &self->enemy->monsterinfo.regen_delay2);

		// hold monsters in-place
		if (self->enemy->svflags & SVF_MONSTER)
			self->enemy->holdtime = level.time + 0.2;
	}
	// the target is a dead monster and needs resurrection
	else if (self->enemy->health < 1)
	{
		M_Reanimate(self->activator, self->enemy, self->monsterinfo.level, 0.33, false);
	}
}
Пример #4
0
void myparasite_fire (edict_t *self)
{
	int		pull;
	int		damage;
	int		para_range	= PARASITE_ATTACK_RANGE;
	vec3_t	v, start, end, forward;
	trace_t	tr;

	// monitor attack duration
	if (self->shots >= PARASITE_ATTACK_FRAMES)
	{
		self->shots = 0;
		//self->oldenemy = self->enemy;
		self->enemy = NULL;
		self->wait = level.time + PARASITE_REFIRE;
		return;
	}

	damage = PARASITE_INITIAL_DMG+PARASITE_ADDON_DMG*self->myskills.abilities[BLOOD_SUCKER].current_level;
	// morph mastery increases damage
	if (self->myskills.abilities[MORPH_MASTERY].current_level > 0)
		damage *= 1.5;

	self->lastsound = level.framenum;
	if (self->shots == 0)
		gi.sound (self, CHAN_AUTO, gi.soundindex("parasite/paratck3.wav"), 1, ATTN_NORM, 0);

	// get muzzle position
	AngleVectors(self->s.angles, forward, NULL, NULL);
	VectorMA(self->s.origin, self->maxs[1]-8, forward, start);
	start[2] += 2;

	// get a valid target if we don't have one already
	if (!parasite_cantarget(self, self->enemy))
	{
		if (!myparasite_findtarget(self))
		{
			self->enemy = NULL;
			//gi.dprintf("couldn't find target\n");
		}
	}

	if (self->enemy)
	{
		// lock-on to target
		//VectorCopy(self->enemy->s.origin, end);
		G_EntMidPoint(self->enemy, end);
		// is this a corpse?
		if (self->enemy->health < 1)
			end[2] -= 8; // aim towards the ground
		VectorSubtract(end, start, v);
		VectorNormalize(v);
		VectorMA(start, para_range, v, end);
		
	}
	else
	{
		AngleVectors(self->client->v_angle, forward, NULL, NULL);
		// fire straight ahead
		VectorMA(start, para_range, forward, end);
	}

	tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT);

	// make sure we are actually hitting our enemy
	//if (tr.ent && (tr.ent==self->enemy))
	if (G_EntExists(tr.ent) && !OnSameTeam(self, tr.ent))
	{
		pull = PARASITE_KNOCKBACK;
		if (tr.ent->groundentity)
			pull *= 2;
		T_Damage(tr.ent, self, self, v, tr.endpos, 
			tr.plane.normal, damage, pull, DAMAGE_NO_ABILITIES, MOD_PARASITE);
		if (self->health < self->max_health)
		{
			self->health += damage;
			if (self->health > self->max_health)
				self->health = self->max_health;
		}
	}

	// make the parasite toungue!
	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_PARASITE_ATTACK);
	gi.WriteShort (self-g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (tr.endpos);
	gi.multicast (start, MULTICAST_PVS);

	self->shots++;
	if (self->shots == PARASITE_ATTACK_FRAMES)
		gi.sound (self, CHAN_AUTO, gi.soundindex("parasite/paratck4.wav"), 1, ATTN_NORM, 0);
}
Пример #5
0
void FireTotem_think(edict_t *self, edict_t *caster)
{
	int talentLevel;
	float chance;
	edict_t *target = NULL;

	//Totem should not work underwater (gee I wonder why).
	if(!self->waterlevel)
	{
		//Talent: Volcanic
		talentLevel = getTalentLevel(caster, TALENT_VOLCANIC);
		chance = 0.02 * talentLevel;

		//Find players in radius and attack them.
		while ((target = findclosestradius(target, self->s.origin, TOTEM_MAX_RANGE)) != NULL)
		{
			if (G_ValidTarget(self, target, true) && (self->s.origin[2]+64>target->s.origin[2]))
			{
				vec3_t forward, end;
				int damage = FIRETOTEM_DAMAGE_BASE + self->monsterinfo.level * FIRETOTEM_DAMAGE_MULT;
				int count = 10 + self->monsterinfo.level;
				int speed = 600;
				float	val, dist;
				qboolean fireball=false;

				// copy target location
				G_EntMidPoint(target, end);

				// calculate distance to target
				dist = distance(end, self->s.origin);

				// move our target point based on projectile and enemy velocity
				VectorMA(end, (float)dist/speed, target->velocity, end);

				//Talent: Volcanic - chance to shoot a fireball
				if (talentLevel > 0 && chance > random())
					fireball = true;

				// aim up
				if (fireball)
					val = ((dist/2048)*(dist/2048)*2048) + (end[2]-self->s.origin[2]);//4.4
				else
					val = ((dist/512)*(dist/512)*512) + (end[2]-self->s.origin[2]);
				if (val < 0)
					val = 0;
				end[2] += val;

				// calculate direction vector to target
				VectorSubtract(end, self->s.origin, forward);
				VectorNormalize(forward);
				
				// don't fire in a perfectly straight line
				forward[1] += 0.05*crandom(); 

				// spawn flames
				if (fireball)
					fire_fireball(self, self->s.origin, forward, 200, 125, 600, 5, 20);//4.4
				else
					ThrowFlame(self, self->s.origin, forward, distance(self->s.origin, target->s.origin), speed, damage, GetRandom(2, 4));
				
				self->lastsound = level.framenum;

				// refire delay
				self->delay = level.time + FRAMETIME;
			}
		}
	}

}