Ejemplo n.º 1
0
static void LoadMapObject(MapObject *m, json_t *node)
{
	memset(m, 0, sizeof *m);
	m->Idx = -1;

	LoadInt(&m->Idx, node, "Index");
	m->Name = GetString(node, "Name");
	LoadPic(&m->Normal.Pic, node, "Pic", "OldPic");
	LoadPic(&m->Wreck.Pic, node, "WreckPic", "OldWreckPic");
	if (m->Normal.Pic)
	{
		// Default offset: centered X, align bottom of tile and sprite
		m->Normal.Offset = Vec2iNew(
			-m->Normal.Pic->size.x / 2,
			TILE_HEIGHT / 2 - m->Normal.Pic->size.y);
		LoadVec2i(&m->Normal.Offset, node, "Offset");
	}
	if (m->Wreck.Pic)
	{
		m->Wreck.Offset = Vec2iScaleDiv(m->Wreck.Pic->size, -2);
		LoadVec2i(&m->Wreck.Offset, node, "WreckOffset");
	}
	// Default tile size
	m->Size = Vec2iNew(TILE_WIDTH, TILE_HEIGHT);
	LoadVec2i(&m->Size, node, "Size");
	LoadInt(&m->Health, node, "Health");
	LoadBulletGuns(&m->DestroyGuns, node, "DestroyGuns");
	json_t *flagsNode = json_find_first_label(node, "Flags");
	if (flagsNode != NULL && flagsNode->child != NULL)
	{
		for (json_t *flagNode = flagsNode->child->child;
			flagNode;
			flagNode = flagNode->next)
		{
			m->Flags |= 1 << StrPlacementFlag(flagNode->text);
		}
	}

	// Special types
	JSON_UTILS_LOAD_ENUM(m->Type, node, "Type", StrMapObjectType);
	switch (m->Type)
	{
	case MAP_OBJECT_TYPE_NORMAL:
		// Do nothing
		break;
	case MAP_OBJECT_TYPE_PICKUP_SPAWNER:
		{
			char *tmp = GetString(node, "Pickup");
			m->u.PickupClass = StrPickupClass(tmp);
			CFREE(tmp);
		}
		break;
	default:
		CASSERT(false, "unknown error");
		break;
	}
}
Ejemplo n.º 2
0
static void LoadStaticExit(Mission *m, json_t *node, char *name)
{
	json_t *exitNode = json_find_first_label(node, name);
	if (!exitNode || !exitNode->child)
	{
		return;
	}
	exitNode = exitNode->child;
	LoadVec2i(&m->u.Static.Exit.Start, exitNode, "Start");
	LoadVec2i(&m->u.Static.Exit.End, exitNode, "End");
}
Ejemplo n.º 3
0
static bool TryLoadStaticMap(Mission *m, json_t *node, int version)
{
	CArrayInit(&m->u.Static.Tiles, sizeof(unsigned short));
	if (version == 1)
	{
		// JSON array
		json_t *tiles = json_find_first_label(node, "Tiles");
		if (!tiles || !tiles->child)
		{
			return false;
		}
		tiles = tiles->child;
		for (tiles = tiles->child; tiles; tiles = tiles->next)
		{
			unsigned short n = (unsigned short)atoi(tiles->text);
			CArrayPushBack(&m->u.Static.Tiles, &n);
		}
	}
	else
	{
		// CSV string
		char *tileCSV = GetString(node, "Tiles");
		char *pch = strtok(tileCSV, ",");
		while (pch != NULL)
		{
			unsigned short n = (unsigned short)atoi(pch);
			CArrayPushBack(&m->u.Static.Tiles, &n);
			pch = strtok(NULL, ",");
		}
		CFREE(tileCSV);
	}

	CArrayInit(&m->u.Static.Items, sizeof(MapObjectPositions));
	LoadStaticItems(m, node, "StaticItems", version);
	if (version < 13)
	{
		LoadStaticItems(m, node, "StaticWrecks", version);
	}
	LoadStaticCharacters(m, node, "StaticCharacters");
	LoadStaticObjectives(m, node, "StaticObjectives");
	LoadStaticKeys(m, node, "StaticKeys");

	LoadVec2i(&m->u.Static.Start, node, "Start");
	LoadStaticExit(m, node, "Exit");

	return true;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
static bool TryLoadMapObject(MapObject *m, json_t *node, const int version)
{
	memset(m, 0, sizeof *m);

	m->Name = GetString(node, "Name");

	// Pic
	json_t *normalNode = json_find_first_label(node, "Pic");
	if (normalNode != NULL && normalNode->child != NULL)
	{
		if (version < 2)
		{
			CPicLoadNormal(&m->Pic, normalNode->child);
		}
		else
		{
			CPicLoadJSON(&m->Pic, normalNode->child);
		}
		// Pic required for map object
		if (!CPicIsLoaded(&m->Pic))
		{
			LOG(LM_MAIN, LL_ERROR, "pic not found for map object(%s)", m->Name);
			goto bail;
		}
	}
	if (CPicIsLoaded(&m->Pic))
	{
		// Default offset: centered X, align bottom of tile and sprite
		const Vec2i size = CPicGetSize(&m->Pic);
		m->Offset = Vec2iNew(-size.x / 2, TILE_HEIGHT / 2 - size.y);
		LoadVec2i(&m->Offset, node, "Offset");
	}

	// Wreck
	if (version < 3)
	{
		// Assume old wreck pic is wreck
		json_t *wreckNode = json_find_first_label(node, "WreckPic");
		if (wreckNode != NULL && wreckNode->child != NULL)
		{
			if (version < 2)
			{
				LoadStr(&m->Wreck, node, "WreckPic");
			}
			else
			{
				LoadStr(&m->Wreck, wreckNode, "Pic");
			}
		}
	}
	else
	{
		LoadStr(&m->Wreck, node, "Wreck");
	}

	// Default tile size
	m->Size = TILE_SIZE;
	LoadVec2i(&m->Size, node, "Size");
	LoadVec2i(&m->PosOffset, node, "PosOffset");
	LoadInt(&m->Health, node, "Health");
	LoadBulletGuns(&m->DestroyGuns, node, "DestroyGuns");

	// Flags
	json_t *flagsNode = json_find_first_label(node, "Flags");
	if (flagsNode != NULL && flagsNode->child != NULL)
	{
		for (json_t *flagNode = flagsNode->child->child;
			flagNode;
			flagNode = flagNode->next)
		{
			m->Flags |= 1 << StrPlacementFlag(flagNode->text);
		}
	}

	LoadBool(&m->DrawLast, node, "DrawLast");

	// Special types
	JSON_UTILS_LOAD_ENUM(m->Type, node, "Type", StrMapObjectType);
	switch (m->Type)
	{
	case MAP_OBJECT_TYPE_NORMAL:
		// Do nothing
		break;
	case MAP_OBJECT_TYPE_PICKUP_SPAWNER:
		{
			char *tmp = GetString(node, "Pickup");
			m->u.PickupClass = StrPickupClass(tmp);
			CFREE(tmp);
		}
		break;
	default:
		CASSERT(false, "unknown error");
		break;
	}

	// DestroySpawn - pickups to spawn on destruction
	json_t *destroySpawnNode = json_find_first_label(node, "DestroySpawn");
	if (destroySpawnNode != NULL && destroySpawnNode->child != NULL)
	{
		CArrayInit(&m->DestroySpawn, sizeof(MapObjectDestroySpawn));
		for (json_t *dsNode = destroySpawnNode->child->child;
			dsNode;
			dsNode = dsNode->next)
		{
			MapObjectDestroySpawn mods;
			memset(&mods, 0, sizeof mods);
			JSON_UTILS_LOAD_ENUM(mods.Type, dsNode, "Type", StrPickupType);
			LoadDouble(&mods.SpawnChance, dsNode, "SpawnChance");
			CArrayPushBack(&m->DestroySpawn, &mods);
		}
	}

	return true;

bail:
	return false;
}