示例#1
0
static const MapObject *LoadMapObjectRef(json_t *itemNode, const int version)
{
	if (version <= 3)
	{
		int idx;
		LoadInt(&idx, itemNode, "Index");
		return IntMapObject(idx);
	}
	else
	{
		const char *moName =
			json_find_first_label(itemNode, "MapObject")->child->text;
		const MapObject *mo = StrMapObject(moName);
		if (mo == NULL && version <= 11 && StrEndsWith(moName, " spawner"))
		{
			char buf[256];
			// Old version had same name for ammo and gun spawner
			char itemName[256];
			strncpy(itemName, moName, strlen(moName) - strlen(" spawner"));
			itemName[strlen(moName) - strlen(" spawner")] = '\0';
			snprintf(buf, 256, "%s ammo spawner", itemName);
			mo = StrMapObject(buf);
		}
		if (mo == NULL)
		{
			LOG(LM_MAP, LL_ERROR, "Failed to load map object (%s)", moName);
		}
		return mo;
	}
}
示例#2
0
void MapObjectsLoadJSON(CArray *classes, json_t *root)
{
	int version;
	LoadInt(&version, root, "Version");
	if (version > VERSION || version <= 0)
	{
		CASSERT(false, "cannot read map objects file version");
		return;
	}

	json_t *pickupsNode = json_find_first_label(root, "MapObjects")->child;
	for (json_t *child = pickupsNode->child; child; child = child->next)
	{
		MapObject m;
		LoadMapObject(&m, child);
		CArrayPushBack(classes, &m);
	}

	ReloadDestructibles(&gMapObjects);
	// Load blood objects
	CArrayClear(&gMapObjects.Bloods);
	for (int i = 0;; i++)
	{
		char buf[CDOGS_FILENAME_MAX];
		sprintf(buf, "blood%d", i);
		if (StrMapObject(buf) == NULL)
		{
			break;
		}
		char *tmp;
		CSTRDUP(tmp, buf);
		CArrayPushBack(&gMapObjects.Bloods, &tmp);
	}
}
static void DrawWreck(
	UIObject *o, GraphicsDevice *g, Vec2i pos, void *vData)
{
	const IndexedEditorBrush *data = vData;
	const char **name =
		CArrayGet(&gMapObjects.Destructibles, data->u.ItemIndex);
	const MapObject *mo = StrMapObject(*name);
	pos = Vec2iAdd(Vec2iAdd(pos, o->Pos), Vec2iScaleDiv(o->Size, 2));
	Vec2i offset;
	const Pic *pic = MapObjectGetPic(mo, &offset, true);
	Blit(g, pic, Vec2iAdd(pos, offset));
}
示例#4
0
MapObject *IntMapObject(const int m)
{
	// Note: do not edit; legacy integer mapping
	static const char *oldMapObjects[] =
	{
		"barrel_blue",
		"box",
		"box2",
		"cabinet",
		"plant",
		"bench",
		"chair",
		"column",
		"barrel_skull",
		"barrel_wood",
		"box_gray",
		"box_green",
		"statue_ogre",
		"table_wood_candle",
		"table_wood",
		"tree_dead",
		"bookshelf",
		"box_wood",
		"table_clothed",
		"table_steel",
		"tree_autumn",
		"tree",
		"box_metal_green",
		"safe",
		"box_red",
		"table_lab",
		"terminal",
		"barrel",
		"rocket",
		"egg",
		"bloodstain",
		"wall_skull",
		"bone_blood",
		"bulletmarks",
		"skull",
		"blood0",
		"scratch",
		"wall_stuff",
		"wall_goo",
		"goo"
	};
	if (m < 0 || m > (int)(sizeof oldMapObjects / sizeof oldMapObjects[0]))
	{
		LOG(LM_MAIN, LL_ERROR, "cannot find map object %d", m);
		return NULL;
	}
	return StrMapObject(oldMapObjects[m]);
}
示例#5
0
static const MapObject *LoadMapObjectRef(json_t *itemNode, const int version)
{
	if (version <= 3)
	{
		int idx;
		LoadInt(&idx, itemNode, "Index");
		return IntMapObject(idx);
	}
	else
	{
		return StrMapObject(
			json_find_first_label(itemNode, "MapObject")->child->text);
	}
}
示例#6
0
void ObjectiveLoadJSON(Objective *o, json_t *node, const int version)
{
	memset(o, 0, sizeof *o);
	o->Description = GetString(node, "Description");
	JSON_UTILS_LOAD_ENUM(o->Type, node, "Type", StrObjectiveType);
	// Set objective colours based on type
	o->color = ObjectiveTypeColor(o->Type);
	if (version < 8)
	{
		// Index numbers used for all objective classes; convert them
		// to their class handles
		LoadInt(&o->u.Index, node, "Index");
		switch (o->Type)
		{
		case OBJECTIVE_COLLECT:
			o->u.Pickup = IntPickupClass(o->u.Index);
			break;
		case OBJECTIVE_DESTROY:
			o->u.MapObject = IntMapObject(o->u.Index);
			break;
		default:
			// do nothing
			break;
		}
	}
	else
	{
		char *tmp;
		switch (o->Type)
		{
		case OBJECTIVE_COLLECT:
			tmp = GetString(node, "Pickup");
			o->u.Pickup = StrPickupClass(tmp);
			CFREE(tmp);
			break;
		case OBJECTIVE_DESTROY:
			tmp = GetString(node, "MapObject");
			o->u.MapObject = StrMapObject(tmp);
			CFREE(tmp);
			break;
		default:
			LoadInt(&o->u.Index, node, "Index");
			break;
		}
	}
	LoadInt(&o->Count, node, "Count");
	LoadInt(&o->Required, node, "Required");
	LoadInt(&o->Flags, node, "Flags");
}
示例#7
0
int DestructibleMapObjectIndex(const MapObject *mo)
{
	if (mo == NULL)
	{
		return 0;
	}
	CA_FOREACH(const char *, name, gMapObjects.Destructibles)
		const MapObject *d = StrMapObject(*name);
		if (d == mo)
		{
			return _ca_index;
		}
	CA_FOREACH_END()
	CASSERT(false, "cannot find destructible map object");
	return -1;
}
static void MissionResetObjectiveIndex(Objective *o)
{
	switch (o->Type)
	{
	case OBJECTIVE_COLLECT:
		o->u.Pickup = IntScorePickupClass(0);
		break;
	case OBJECTIVE_DESTROY:
		{
			const char **destructibleName =
				CArrayGet(&gMapObjects.Destructibles, 0);
			o->u.MapObject = StrMapObject(*destructibleName);
		}
		CASSERT(o->u.MapObject != NULL, "cannot find map object");
		break;
	default:
		o->u.Index = 0;
		break;
	}
}
static UIObject *CreateAddWreckObjs(Vec2i pos, EditorBrush *brush)
{
	UIObject *o2;
	UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero());

	UIObject *o = UIObjectCreate(
		UITYPE_CUSTOM, 0,
		Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4));
	o->ChangeFunc = BrushSetBrushTypeAddWreck;
	o->u.CustomDrawFunc = DrawWreck;
	o->OnFocusFunc = ActivateIndexedEditorBrush;
	o->OnUnfocusFunc = DeactivateIndexedEditorBrush;
	pos = Vec2iZero();
	const int width = 8;
	for (int i = 0; i < (int)gMapObjects.Destructibles.size; i++)
	{
		o2 = UIObjectCopy(o);
		o2->IsDynamicData = 1;
		CMALLOC(o2->Data, sizeof(IndexedEditorBrush));
		((IndexedEditorBrush *)o2->Data)->Brush = brush;
		((IndexedEditorBrush *)o2->Data)->u.ItemIndex = i;
		o2->Pos = pos;
		UIObjectAddChild(c, o2);
		pos.x += o->Size.x;
		if (((i + 1) % width) == 0)
		{
			pos.x = 0;
			pos.y += o->Size.y;
		}
		const char **name = CArrayGet(&gMapObjects.Destructibles, i);
		const MapObject *mo = StrMapObject(*name);
		CSTRDUP(o2->Tooltip, mo->Name);
	}

	UIObjectDestroy(o);
	return c;
}
示例#10
0
void ObjAdd(const NMapObjectAdd amo)
{
	// Find an empty slot in object list
	TObject *o = NULL;
	int i;
	for (i = 0; i < (int)gObjs.size; i++)
	{
		TObject *obj = CArrayGet(&gObjs, i);
		if (!obj->isInUse)
		{
			o = obj;
			break;
		}
	}
	if (o == NULL)
	{
		TObject obj;
		memset(&obj, 0, sizeof obj);
		CArrayPushBack(&gObjs, &obj);
		i = (int)gObjs.size - 1;
		o = CArrayGet(&gObjs, i);
	}
	memset(o, 0, sizeof *o);
	o->uid = amo.UID;
	o->Class = StrMapObject(amo.MapObjectClass);
	o->Health = amo.Health;
	o->tileItem.x = o->tileItem.y = -1;
	o->tileItem.flags = amo.TileItemFlags;
	o->tileItem.kind = KIND_OBJECT;
	o->tileItem.getPicFunc = GetObjectPic;
	o->tileItem.getActorPicsFunc = NULL;
	o->tileItem.size = o->Class->Size;
	o->tileItem.id = i;
	MapTryMoveTileItem(&gMap, &o->tileItem, Net2Vec2i(amo.Pos));
	o->isInUse = true;
}
示例#11
0
MapObject *RandomBloodMapObject(const MapObjects *mo)
{
	const int idx = rand() % (int)mo->Bloods.size;
	const char **name = CArrayGet(&mo->Bloods, idx);
	return StrMapObject(*name);
}
示例#12
0
EditorResult EditorBrushStartPainting(EditorBrush *b, Mission *m, int isMain)
{
	if (!b->IsPainting)
	{
		b->LastPos = b->Pos;
	}
	b->PaintType = isMain ? b->MainType : b->SecondaryType;
	switch (b->Type)
	{
	case BRUSHTYPE_POINT:
		b->IsPainting = true;
		EditorBrushPaintLine(b, m);
		return EDITOR_RESULT_CHANGED;
	case BRUSHTYPE_LINE:	// fallthrough
	case BRUSHTYPE_BOX:	// fallthrough
	case BRUSHTYPE_BOX_FILLED:	// fallthrough
	case BRUSHTYPE_ROOM:	// fallthrough
	case BRUSHTYPE_SET_EXIT:
		// don't paint until the end
		break;
	case BRUSHTYPE_ROOM_PAINTER:
		EditorBrushPaintRoom(b, m);
		return EDITOR_RESULT_CHANGED;
	case BRUSHTYPE_SELECT:
		// Perform state changes if we've started painting
		if (!b->IsPainting)
		{
			if (!b->IsMoving)
			{
				// check if the click was inside the selection
				// If so, start moving
				if (b->Pos.x >= b->SelectionStart.x &&
					b->Pos.y >= b->SelectionStart.y &&
					b->Pos.x < b->SelectionStart.x + b->SelectionSize.x &&
					b->Pos.y < b->SelectionStart.y + b->SelectionSize.y)
				{
					b->IsMoving = 1;
					b->DragPos = b->Pos;
				}
			}
		}
		break;
	case BRUSHTYPE_FILL:
		// Use flood fill to change all the tiles of the same type to
		// another type
		// Don't paint if target already same type
		// Special case: don't flood-fill doors
		if ((MissionGetTile(m, b->Pos) & MAP_MASKACCESS) != b->PaintType &&
			b->PaintType != MAP_DOOR)
		{
			FloodFillData data;
			data.Fill = MissionFillTile;
			data.IsSame = MissionIsTileSame;
			PaintFloodFillData pData;
			pData.m = m;
			pData.fromType = MissionGetTile(m, b->Pos) & MAP_MASKACCESS;
			pData.toType = b->PaintType;
			data.data = &pData;
			if (CFloodFill(b->Pos, &data))
			{
				return EDITOR_RESULT_CHANGED;
			}
		}
		return EDITOR_RESULT_NONE;
	case BRUSHTYPE_SET_PLAYER_START:
		if (MissionGetTile(m, b->Pos) == MAP_ROOM ||
			MissionGetTile(m, b->Pos) == MAP_FLOOR)
		{
			m->u.Static.Start = b->Pos;
			return EDITOR_RESULT_CHANGED;
		}
		break;
	case BRUSHTYPE_ADD_ITEM:
		if (isMain)
		{
			if (MissionStaticTryAddItem(m, b->u.MapObject, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryRemoveItemAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	case BRUSHTYPE_ADD_WRECK:
		if (isMain)
		{
			const char **destructibleName =
				CArrayGet(&gMapObjects.Destructibles, b->u.ItemIndex);
			if (MissionStaticTryAddWreck(
				m, StrMapObject(*destructibleName), b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryRemoveWreckAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	case BRUSHTYPE_ADD_CHARACTER:
		if (isMain)
		{
			if (MissionStaticTryAddCharacter(m, b->u.ItemIndex, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryRemoveCharacterAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	case BRUSHTYPE_ADD_OBJECTIVE:
		if (isMain)
		{
			if (MissionStaticTryAddObjective(
				m, b->u.ItemIndex, b->Index2, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryRemoveObjectiveAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	case BRUSHTYPE_ADD_KEY:
		if (isMain)
		{
			if (MissionStaticTryAddKey(m, b->u.ItemIndex, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryRemoveKeyAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	case BRUSHTYPE_SET_KEY:
		if (isMain || b->u.ItemIndex > 0)
		{
			if (MissionStaticTrySetKey(m, b->u.ItemIndex, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		else
		{
			if (MissionStaticTryUnsetKeyAt(m, b->Pos))
			{
				return EDITOR_RESULT_CHANGED_AND_RELOAD;
			}
		}
		break;
	default:
		assert(0 && "unknown brush type");
		break;
	}
	b->IsPainting = 1;
	return EDITOR_RESULT_NONE;
}
示例#13
0
void LoadMissions(CArray *missions, json_t *missionsNode, int version)
{
	json_t *child;
	for (child = missionsNode->child; child; child = child->next)
	{
		Mission m;
		MissionInit(&m);
		m.Title = GetString(child, "Title");
		m.Description = GetString(child, "Description");
		JSON_UTILS_LOAD_ENUM(m.Type, child, "Type", StrMapType);
		LoadInt(&m.Size.x, child, "Width");
		LoadInt(&m.Size.y, child, "Height");
		if (version <= 10)
		{
			int style;
			LoadInt(&style, child, "WallStyle");
			strcpy(m.WallStyle, IntWallStyle(style));
			LoadInt(&style, child, "FloorStyle");
			strcpy(m.FloorStyle, IntFloorStyle(style));
			LoadInt(&style, child, "RoomStyle");
			strcpy(m.RoomStyle, IntRoomStyle(style));
		}
		else
		{
			char *tmp = GetString(child, "WallStyle");
			strcpy(m.WallStyle, tmp);
			CFREE(tmp);
			tmp = GetString(child, "FloorStyle");
			strcpy(m.FloorStyle, tmp);
			CFREE(tmp);
			tmp = GetString(child, "RoomStyle");
			strcpy(m.RoomStyle, tmp);
			CFREE(tmp);
		}
		if (version <= 9)
		{
			int style;
			LoadInt(&style, child, "ExitStyle");
			strcpy(m.ExitStyle, IntExitStyle(style));
		}
		else
		{
			char *tmp = GetString(child, "ExitStyle");
			strcpy(m.ExitStyle, tmp);
			CFREE(tmp);
		}
		if (version <= 8)
		{
			int keyStyle;
			LoadInt(&keyStyle, child, "KeyStyle");
			strcpy(m.KeyStyle, IntKeyStyle(keyStyle));
		}
		else
		{
			char *tmp = GetString(child, "KeyStyle");
			strcpy(m.KeyStyle, tmp);
			CFREE(tmp);
		}
		if (version <= 5)
		{
			int doorStyle;
			LoadInt(&doorStyle, child, "DoorStyle");
			strcpy(m.DoorStyle, IntDoorStyle(doorStyle));
		}
		else
		{
			char *tmp = GetString(child, "DoorStyle");
			strcpy(m.DoorStyle, tmp);
			CFREE(tmp);
		}
		LoadMissionObjectives(
			&m.Objectives,
			json_find_first_label(child, "Objectives")->child,
			version);
		LoadIntArray(&m.Enemies, child, "Enemies");
		LoadIntArray(&m.SpecialChars, child, "SpecialChars");
		if (version <= 3)
		{
			CArray items;
			CArrayInit(&items, sizeof(int));
			LoadIntArray(&items, child, "Items");
			CArray densities;
			CArrayInit(&densities, sizeof(int));
			LoadIntArray(&densities, child, "ItemDensities");
			for (int i = 0; i < (int)items.size; i++)
			{
				MapObjectDensity mod;
				mod.M = IntMapObject(*(int *)CArrayGet(&items, i));
				mod.Density = *(int *)CArrayGet(&densities, i);
				CArrayPushBack(&m.MapObjectDensities, &mod);
			}
		}
		else
		{
			json_t *modsNode =
				json_find_first_label(child, "MapObjectDensities");
			if (modsNode && modsNode->child)
			{
				modsNode = modsNode->child;
				for (json_t *modNode = modsNode->child;
					modNode;
					modNode = modNode->next)
				{
					MapObjectDensity mod;
					mod.M = StrMapObject(
						json_find_first_label(modNode, "MapObject")->child->text);
					LoadInt(&mod.Density, modNode, "Density");
					CArrayPushBack(&m.MapObjectDensities, &mod);
				}
			}
		}
		LoadInt(&m.EnemyDensity, child, "EnemyDensity");
		LoadWeapons(
			&m.Weapons, json_find_first_label(child, "Weapons")->child);
		strcpy(m.Song, json_find_first_label(child, "Song")->child->text);
		if (version <= 4)
		{
			// Load colour indices
			int wc, fc, rc, ac;
			LoadInt(&wc, child, "WallColor");
			LoadInt(&fc, child, "FloorColor");
			LoadInt(&rc, child, "RoomColor");
			LoadInt(&ac, child, "AltColor");
			m.WallMask = RangeToColor(wc);
			m.FloorMask = RangeToColor(fc);
			m.RoomMask = RangeToColor(rc);
			m.AltMask = RangeToColor(ac);
		}
		else
		{
			LoadColor(&m.WallMask, child, "WallMask");
			LoadColor(&m.FloorMask, child, "FloorMask");
			LoadColor(&m.RoomMask, child, "RoomMask");
			LoadColor(&m.AltMask, child, "AltMask");
		}
		switch (m.Type)
		{
		case MAPTYPE_CLASSIC:
			LoadInt(&m.u.Classic.Walls, child, "Walls");
			LoadInt(&m.u.Classic.WallLength, child, "WallLength");
			LoadInt(&m.u.Classic.CorridorWidth, child, "CorridorWidth");
			LoadClassicRooms(
				&m, json_find_first_label(child, "Rooms")->child);
			LoadInt(&m.u.Classic.Squares, child, "Squares");
			LoadClassicDoors(&m, child, "Doors");
			LoadClassicPillars(&m, child, "Pillars");
			break;
		case MAPTYPE_STATIC:
			if (!TryLoadStaticMap(&m, child, version))
			{
				continue;
			}
			break;
		case MAPTYPE_CAVE:
			LoadInt(&m.u.Cave.FillPercent, child, "FillPercent");
			LoadInt(&m.u.Cave.Repeat, child, "Repeat");
			LoadInt(&m.u.Cave.R1, child, "R1");
			LoadInt(&m.u.Cave.R2, child, "R2");
			break;
		default:
			assert(0 && "unknown map type");
			continue;
		}
		CArrayPushBack(missions, &m);
	}
}