예제 #1
0
static void LoadBullet(
	BulletClass *b, json_t *node, const BulletClass *defaultBullet)
{
	memset(b, 0, sizeof *b);
	if (defaultBullet != NULL)
	{
		memcpy(b, defaultBullet, sizeof *b);
		if (defaultBullet->HitSound.Object != NULL)
		{
			CSTRDUP(b->HitSound.Object, defaultBullet->HitSound.Object);
		}
		if (defaultBullet->HitSound.Flesh != NULL)
		{
			CSTRDUP(b->HitSound.Flesh, defaultBullet->HitSound.Flesh);
		}
		if (defaultBullet->HitSound.Wall != NULL)
		{
			CSTRDUP(b->HitSound.Wall, defaultBullet->HitSound.Wall);
		}
		// TODO: enable default bullet guns?
		memset(&b->Falling.DropGuns, 0, sizeof b->Falling.DropGuns);
		memset(&b->OutOfRangeGuns, 0, sizeof b->OutOfRangeGuns);
		memset(&b->HitGuns, 0, sizeof b->HitGuns);
		memset(&b->ProximityGuns, 0, sizeof b->ProximityGuns);
	}
	char *tmp;

	LoadStr(&b->Name, node, "Name");
	if (json_find_first_label(node, "Pic"))
	{
		json_t *pic = json_find_first_label(node, "Pic")->child;
		tmp = GetString(pic, "Type");
		b->CPic.Type = StrPicType(tmp);
		CFREE(tmp);
		bool picLoaded = false;
		switch (b->CPic.Type)
		{
		case PICTYPE_NORMAL:
			tmp = GetString(pic, "Pic");
			b->CPic.u.Pic = PicManagerGetPic(&gPicManager, tmp);
			CFREE(tmp);
			picLoaded = b->CPic.u.Pic != NULL;
			break;
		case PICTYPE_DIRECTIONAL:
			tmp = GetString(pic, "Sprites");
			b->CPic.u.Sprites =
				&PicManagerGetSprites(&gPicManager, tmp)->pics;
			CFREE(tmp);
			picLoaded = b->CPic.u.Sprites != NULL;
			break;
		case PICTYPE_ANIMATED:	// fallthrough
		case PICTYPE_ANIMATED_RANDOM:
			tmp = GetString(pic, "Sprites");
			b->CPic.u.Animated.Sprites =
				&PicManagerGetSprites(&gPicManager, tmp)->pics;
			CFREE(tmp);
			LoadInt(&b->CPic.u.Animated.Count, pic, "Count");
			LoadInt(&b->CPic.u.Animated.TicksPerFrame, pic, "TicksPerFrame");
			// Set safe default ticks per frame 1;
			// if 0 then this leads to infinite loop when animating
			b->CPic.u.Animated.TicksPerFrame = MAX(
				b->CPic.u.Animated.TicksPerFrame, 1);
			picLoaded = b->CPic.u.Animated.Sprites != NULL;
			break;
		default:
			CASSERT(false, "unknown pic type");
			break;
		}
		b->CPic.UseMask = true;
		b->CPic.u1.Mask = colorWhite;
		if (json_find_first_label(pic, "Mask"))
		{
			tmp = GetString(pic, "Mask");
			b->CPic.u1.Mask = StrColor(tmp);
			CFREE(tmp);
		}
		else if (json_find_first_label(pic, "Tint"))
		{
			b->CPic.UseMask = false;
			json_t *tint = json_find_first_label(pic, "Tint")->child->child;
			b->CPic.u1.Tint.h = atof(tint->text);
			tint = tint->next;
			b->CPic.u1.Tint.s = atof(tint->text);
			tint = tint->next;
			b->CPic.u1.Tint.v = atof(tint->text);
		}
		if ((json_find_first_label(pic, "OldPic") &&
			ConfigGetBool(&gConfig, "Graphics.OriginalPics")) ||
			!picLoaded)
		{
			int oldPic = PIC_UZIBULLET;
			LoadInt(&oldPic, pic, "OldPic");
			b->CPic.Type = PICTYPE_NORMAL;
			b->CPic.u.Pic = PicManagerGetFromOld(&gPicManager, oldPic);
		}
	}
	LoadVec2i(&b->ShadowSize, node, "ShadowSize");
	LoadInt(&b->Delay, node, "Delay");
	if (json_find_first_label(node, "Speed"))
	{
		LoadInt(&b->SpeedLow, node, "Speed");
		b->SpeedHigh = b->SpeedLow;
	}
	if (json_find_first_label(node, "SpeedLow"))
	{
		LoadInt(&b->SpeedLow, node, "SpeedLow");
	}
	if (json_find_first_label(node, "SpeedHigh"))
	{
		LoadInt(&b->SpeedHigh, node, "SpeedHigh");
	}
	b->SpeedLow = MIN(b->SpeedLow, b->SpeedHigh);
	b->SpeedHigh = MAX(b->SpeedLow, b->SpeedHigh);
	LoadBool(&b->SpeedScale, node, "SpeedScale");
	LoadInt(&b->Friction, node, "Friction");
	if (json_find_first_label(node, "Range"))
	{
		LoadInt(&b->RangeLow, node, "Range");
		b->RangeHigh = b->RangeLow;
	}
	if (json_find_first_label(node, "RangeLow"))
	{
		LoadInt(&b->RangeLow, node, "RangeLow");
	}
	if (json_find_first_label(node, "RangeHigh"))
	{
		LoadInt(&b->RangeHigh, node, "RangeHigh");
	}
	b->RangeLow = MIN(b->RangeLow, b->RangeHigh);
	b->RangeHigh = MAX(b->RangeLow, b->RangeHigh);
	LoadInt(&b->Power, node, "Power");
	LoadVec2i(&b->Size, node, "Size");
	if (json_find_first_label(node, "Special"))
	{
		tmp = GetString(node, "Special");
		b->Special = StrSpecialDamage(tmp);
		CFREE(tmp);
	}
	LoadBool(&b->HurtAlways, node, "HurtAlways");
	LoadBool(&b->Persists, node, "Persists");
	if (json_find_first_label(node, "Spark"))
	{
		tmp = GetString(node, "Spark");
		b->Spark = StrParticleClass(&gParticleClasses, tmp);
		CFREE(tmp);
	}
	if (json_find_first_label(node, "HitSounds"))
	{
		json_t *hitSounds = json_find_first_label(node, "HitSounds")->child;
		CFREE(b->HitSound.Object);
		b->HitSound.Object = NULL;
		LoadStr(&b->HitSound.Object, hitSounds, "Object");
		CFREE(b->HitSound.Flesh);
		b->HitSound.Flesh = NULL;
		LoadStr(&b->HitSound.Flesh, hitSounds, "Flesh");
		CFREE(b->HitSound.Wall);
		b->HitSound.Wall = NULL;
		LoadStr(&b->HitSound.Wall, hitSounds, "Wall");
	}
	LoadBool(&b->WallBounces, node, "WallBounces");
	LoadBool(&b->HitsObjects, node, "HitsObjects");
	if (json_find_first_label(node, "Falling"))
	{
		json_t *falling = json_find_first_label(node, "Falling")->child;
		LoadInt(&b->Falling.GravityFactor, falling, "GravityFactor");
		LoadBool(&b->Falling.FallsDown, falling, "FallsDown");
		LoadBool(&b->Falling.DestroyOnDrop, falling, "DestroyOnDrop");
		LoadBool(&b->Falling.Bounces, falling, "Bounces");
	}
	LoadInt(&b->SeekFactor, node, "SeekFactor");
	LoadBool(&b->Erratic, node, "Erratic");

	b->node = node;
}
예제 #2
0
파일: objs.c 프로젝트: evktalo/cdogs-sdl
static bool DoDamageCharacter(
	const Vec2i pos,
	const Vec2i hitVector,
	const int power,
	const int flags,
	const int player,
	const int uid,
	const TTileItem *target,
	const special_damage_e special,
	const HitSounds *hitSounds,
	const bool allowFriendlyHitSound)
{
	// Create events: hit, damage, score
	TActor *actor = CArrayGet(&gActors, target->id);
	CASSERT(actor->isInUse, "Cannot damage nonexistent player");
	bool canHit = CanHitCharacter(flags, uid, actor);
	if (canHit)
	{
		GameEvent e;
		e.Type = GAME_EVENT_HIT_CHARACTER;
		e.u.HitCharacter.TargetId = actor->tileItem.id;
		e.u.HitCharacter.Special = special;
		GameEventsEnqueue(&gGameEvents, e);
		if (gConfig.Sound.Hits && hitSounds != NULL &&
			!ActorIsImmune(actor, special) &&
			(allowFriendlyHitSound || !ActorIsInvulnerable(
			actor, flags, player, gCampaign.Entry.Mode)))
		{
			GameEvent es;
			es.Type = GAME_EVENT_SOUND_AT;
			es.u.SoundAt.Sound = hitSounds->Flesh;
			es.u.SoundAt.Pos = pos;
			GameEventsEnqueue(&gGameEvents, es);
		}
		if (gConfig.Game.ShotsPushback)
		{
			GameEvent ei;
			ei.Type = GAME_EVENT_ACTOR_IMPULSE;
			ei.u.ActorImpulse.Id = actor->tileItem.id;
			ei.u.ActorImpulse.Vel = Vec2iScaleDiv(
				Vec2iScale(hitVector, power), SHOT_IMPULSE_DIVISOR);
			GameEventsEnqueue(&gGameEvents, ei);
		}
		if (CanDamageCharacter(flags, player, uid, actor, special))
		{
			GameEvent e1;
			e1.Type = GAME_EVENT_DAMAGE_CHARACTER;
			e1.u.DamageCharacter.Power = power;
			e1.u.DamageCharacter.PlayerIndex = player;
			e1.u.DamageCharacter.TargetId = actor->tileItem.id;
			e1.u.DamageCharacter.TargetPlayerIndex = -1;
			if (actor->pData)
			{
				e1.u.DamageCharacter.TargetPlayerIndex =
					actor->pData->playerIndex;
			}
			GameEventsEnqueue(&gGameEvents, e1);

			if (gConfig.Game.Gore != GORE_NONE)
			{
				GameEvent eb;
				memset(&eb, 0, sizeof eb);
				eb.Type = GAME_EVENT_ADD_PARTICLE;
				eb.u.AddParticle.FullPos = Vec2iReal2Full(pos);
				eb.u.AddParticle.Z = 10 * Z_FACTOR;
				int bloodPower = power * 2;
				int bloodSize = 1;
				while (bloodPower > 0)
				{
					switch (bloodSize)
					{
					case 1:
						eb.u.AddParticle.Class =
							StrParticleClass(&gParticleClasses, "blood1");
						break;
					case 2:
						eb.u.AddParticle.Class =
							StrParticleClass(&gParticleClasses, "blood2");
						break;
					default:
						eb.u.AddParticle.Class =
							StrParticleClass(&gParticleClasses, "blood3");
						break;
					}
					bloodSize++;
					if (bloodSize > 3)
					{
						bloodSize = 1;
					}
					if (gConfig.Game.ShotsPushback)
					{
						eb.u.AddParticle.Vel = Vec2iScaleDiv(
							Vec2iScale(hitVector, (rand() % 8 + 8) * power),
							15 * SHOT_IMPULSE_DIVISOR);
					}
					else
					{
						eb.u.AddParticle.Vel = Vec2iScaleDiv(
							Vec2iScale(hitVector, rand() % 8 + 8), 20);
					}
					eb.u.AddParticle.Vel.x += (rand() % 128) - 64;
					eb.u.AddParticle.Vel.y += (rand() % 128) - 64;
					eb.u.AddParticle.Angle = RAND_DOUBLE(0, PI * 2);
					eb.u.AddParticle.DZ = (rand() % 6) + 6;
					eb.u.AddParticle.Spin = RAND_DOUBLE(-0.1, 0.1);
					GameEventsEnqueue(&gGameEvents, eb);
					switch (gConfig.Game.Gore)
					{
					case GORE_LOW:
						bloodPower /= 8;
						break;
					case GORE_MEDIUM:
						bloodPower /= 2;
						break;
					default:
						bloodPower = bloodPower * 7 / 8;
						break;
					}
				}
			}

			if (player >= 0 && power != 0)
			{
				// Calculate score based on
				// if they hit a penalty character
				GameEvent e2;
				e2.Type = GAME_EVENT_SCORE;
				e2.u.Score.PlayerIndex = player;
				if (actor->flags & FLAGS_PENALTY)
				{
					e2.u.Score.Score = PENALTY_MULTIPLIER * power;
				}
				else
				{
					e2.u.Score.Score = power;
				}
				GameEventsEnqueue(&gGameEvents, e2);
			}
		}
	}
	return canHit;
}
예제 #3
0
static void LoadBullet(
	BulletClass *b, json_t *node, const BulletClass *defaultBullet)
{
	memset(b, 0, sizeof *b);
	if (defaultBullet != NULL)
	{
		memcpy(b, defaultBullet, sizeof *b);
		if (defaultBullet->Name != NULL)
		{
			CSTRDUP(b->Name, defaultBullet->Name);
		}
		if (defaultBullet->HitSound.Object != NULL)
		{
			CSTRDUP(b->HitSound.Object, defaultBullet->HitSound.Object);
		}
		if (defaultBullet->HitSound.Flesh != NULL)
		{
			CSTRDUP(b->HitSound.Flesh, defaultBullet->HitSound.Flesh);
		}
		if (defaultBullet->HitSound.Wall != NULL)
		{
			CSTRDUP(b->HitSound.Wall, defaultBullet->HitSound.Wall);
		}
		// TODO: enable default bullet guns?
		memset(&b->Falling.DropGuns, 0, sizeof b->Falling.DropGuns);
		memset(&b->OutOfRangeGuns, 0, sizeof b->OutOfRangeGuns);
		memset(&b->HitGuns, 0, sizeof b->HitGuns);
		memset(&b->ProximityGuns, 0, sizeof b->ProximityGuns);
	}

	char *tmp;

	tmp = NULL;
	LoadStr(&tmp, node, "Name");
	if (tmp != NULL)
	{
		CFREE(b->Name);
		b->Name = tmp;
	}
	if (json_find_first_label(node, "Pic"))
	{
		CPicLoadJSON(&b->CPic, json_find_first_label(node, "Pic")->child);
	}
	LoadVec2i(&b->ShadowSize, node, "ShadowSize");
	LoadInt(&b->Delay, node, "Delay");
	if (json_find_first_label(node, "Speed"))
	{
		LoadInt(&b->SpeedLow, node, "Speed");
		b->SpeedHigh = b->SpeedLow;
	}
	LoadInt(&b->SpeedLow, node, "SpeedLow");
	LoadInt(&b->SpeedHigh, node, "SpeedHigh");
	b->SpeedLow = MIN(b->SpeedLow, b->SpeedHigh);
	b->SpeedHigh = MAX(b->SpeedLow, b->SpeedHigh);
	LoadBool(&b->SpeedScale, node, "SpeedScale");
	LoadInt(&b->Friction, node, "Friction");
	if (json_find_first_label(node, "Range"))
	{
		LoadInt(&b->RangeLow, node, "Range");
		b->RangeHigh = b->RangeLow;
	}
	LoadInt(&b->RangeLow, node, "RangeLow");
	LoadInt(&b->RangeHigh, node, "RangeHigh");
	b->RangeLow = MIN(b->RangeLow, b->RangeHigh);
	b->RangeHigh = MAX(b->RangeLow, b->RangeHigh);
	LoadInt(&b->Power, node, "Power");
	LoadVec2i(&b->Size, node, "Size");
	tmp = NULL;
	LoadStr(&tmp, node, "Special");
	if (tmp != NULL)
	{
		b->Special = StrSpecialDamage(tmp);
		CFREE(tmp);
	}
	LoadBool(&b->HurtAlways, node, "HurtAlways");
	LoadBool(&b->Persists, node, "Persists");
	tmp = NULL;
	LoadStr(&tmp, node, "Spark");
	if (tmp != NULL)
	{
		b->Spark = StrParticleClass(&gParticleClasses, tmp);
		CFREE(tmp);
	}
	if (json_find_first_label(node, "HitSounds"))
	{
		json_t *hitSounds = json_find_first_label(node, "HitSounds")->child;
		CFREE(b->HitSound.Object);
		b->HitSound.Object = NULL;
		LoadStr(&b->HitSound.Object, hitSounds, "Object");
		CFREE(b->HitSound.Flesh);
		b->HitSound.Flesh = NULL;
		LoadStr(&b->HitSound.Flesh, hitSounds, "Flesh");
		CFREE(b->HitSound.Wall);
		b->HitSound.Wall = NULL;
		LoadStr(&b->HitSound.Wall, hitSounds, "Wall");
	}
	LoadBool(&b->WallBounces, node, "WallBounces");
	LoadBool(&b->HitsObjects, node, "HitsObjects");
	if (json_find_first_label(node, "Falling"))
	{
		json_t *falling = json_find_first_label(node, "Falling")->child;
		LoadInt(&b->Falling.GravityFactor, falling, "GravityFactor");
		LoadBool(&b->Falling.FallsDown, falling, "FallsDown");
		LoadBool(&b->Falling.DestroyOnDrop, falling, "DestroyOnDrop");
		LoadBool(&b->Falling.Bounces, falling, "Bounces");
	}
	LoadInt(&b->SeekFactor, node, "SeekFactor");
	LoadBool(&b->Erratic, node, "Erratic");

	b->node = node;

	LOG(LM_MAP, LL_DEBUG,
		"loaded bullet name(%s) shadowSize(%d, %d) delay(%d) speed(%d-%d)...",
		b->Name != NULL ? b->Name : "", b->ShadowSize.x, b->ShadowSize.y,
		b->Delay, b->SpeedLow, b->SpeedHigh);
	LOG(LM_MAP, LL_DEBUG,
		"...speedScale(%s) friction(%d) range(%d-%d) power(%d)...",
		b->SpeedScale ? "true" : "false", b->Friction,
		b->RangeLow, b->RangeHigh, b->Power);
	LOG(LM_MAP, LL_DEBUG,
		"...size(%d, %d) hurtAlways(%s) persists(%s) spark(%s)...",
		b->Size.x, b->Size.y, b->HurtAlways ? "true" : "false",
		b->Persists ? "true" : "false",
		b->Spark != NULL ? b->Spark->Name : "");
	LOG(LM_MAP, LL_DEBUG,
		"...hitSounds(object(%s), flesh(%s), wall(%s)) wallBounces(%s)...",
		b->HitSound.Object != NULL ? b->HitSound.Object : "",
		b->HitSound.Flesh != NULL ? b->HitSound.Flesh : "",
		b->HitSound.Wall != NULL ? b->HitSound.Wall : "",
		b->WallBounces ? "true" : "false");
	LOG(LM_MAP, LL_DEBUG,
		"...hitsObjects(%s) gravity(%d) fallsDown(%s) destroyOnDrop(%s)...",
		b->HitsObjects ? "true" : "false", b->Falling.GravityFactor,
		b->Falling.FallsDown ? "true" : "false",
		b->Falling.DestroyOnDrop ? "true" : "false");
	LOG(LM_MAP, LL_DEBUG,
		"...dropGuns(%d) seekFactor(%d) erratic(%s)...",
		(int)b->Falling.DropGuns.size, b->SeekFactor,
		b->Erratic ? "true" : "false");
	LOG(LM_MAP, LL_DEBUG,
		"...outOfRangeGuns(%d) hitGuns(%d) proximityGuns(%d)",
		(int)b->OutOfRangeGuns.size,
		(int)b->HitGuns.size,
		(int)b->ProximityGuns.size);
}
예제 #4
0
static void LoadGunDescription(
	GunDescription *g, json_t *node, const GunDescription *defaultGun)
{
	memset(g, 0, sizeof *g);
	g->AmmoId = -1;
	if (defaultGun)
	{
		memcpy(g, defaultGun, sizeof *g);
		if (defaultGun->name)
		{
			CSTRDUP(g->name, defaultGun->name);
		}
		if (defaultGun->Description)
		{
			CSTRDUP(g->Description, defaultGun->Description);
		}
		g->MuzzleHeight /= Z_FACTOR;
	}
	char *tmp;

	if (json_find_first_label(node, "Pic"))
	{
		tmp = GetString(node, "Pic");
		if (strcmp(tmp, "blaster") == 0)
		{
			g->pic = GUNPIC_BLASTER;
		}
		else if (strcmp(tmp, "knife") == 0)
		{
			g->pic = GUNPIC_KNIFE;
		}
		else
		{
			g->pic = -1;
		}
		CFREE(tmp);
	}

	if (json_find_first_label(node, "Icon"))
	{
		tmp = GetString(node, "Icon");
		g->Icon = PicManagerGet(&gPicManager, tmp, -1);
		CFREE(tmp);
	}

	g->name = GetString(node, "Name");

	if (json_find_first_label(node, "Description"))
	{
		g->Description = GetString(node, "Description");
	}

	if (json_find_first_label(node, "Bullet"))
	{
		tmp = GetString(node, "Bullet");
		g->Bullet = StrBulletClass(tmp);
		CFREE(tmp);
	}

	if (json_find_first_label(node, "Ammo"))
	{
		tmp = GetString(node, "Ammo");
		g->AmmoId = StrAmmoId(tmp);
		CFREE(tmp);
	}

	LoadInt(&g->Cost, node, "Cost");

	LoadInt(&g->Lock, node, "Lock");

	LoadInt(&g->ReloadLead, node, "ReloadLead");

	LoadSoundFromNode(&g->Sound, node, "Sound");
	LoadSoundFromNode(&g->ReloadSound, node, "ReloadSound");
	LoadSoundFromNode(&g->SwitchSound, node, "SwitchSound");

	LoadInt(&g->SoundLockLength, node, "SoundLockLength");

	LoadDouble(&g->Recoil, node, "Recoil");

	LoadInt(&g->Spread.Count, node, "SpreadCount");
	LoadDouble(&g->Spread.Width, node, "SpreadWidth");
	LoadDouble(&g->AngleOffset, node, "AngleOffset");

	LoadInt(&g->MuzzleHeight, node, "MuzzleHeight");
	g->MuzzleHeight *= Z_FACTOR;
	if (json_find_first_label(node, "Elevation"))
	{
		LoadInt(&g->ElevationLow, node, "Elevation");
		g->ElevationHigh = g->ElevationLow;
	}
	LoadInt(&g->ElevationLow, node, "ElevationLow");
	LoadInt(&g->ElevationHigh, node, "ElevationHigh");
	g->ElevationLow = MIN(g->ElevationLow, g->ElevationHigh);
	g->ElevationHigh = MAX(g->ElevationLow, g->ElevationHigh);
	if (json_find_first_label(node, "MuzzleFlashParticle"))
	{
		tmp = GetString(node, "MuzzleFlashParticle");
		g->MuzzleFlash = StrParticleClass(&gParticleClasses, tmp);
		CFREE(tmp);
	}

	if (json_find_first_label(node, "Brass"))
	{
		tmp = GetString(node, "Brass");
		g->Brass = StrParticleClass(&gParticleClasses, tmp);
		CFREE(tmp);
	}

	LoadBool(&g->CanShoot, node, "CanShoot");

	LoadInt(&g->ShakeAmount, node, "ShakeAmount");

	g->IsRealGun = true;
}