예제 #1
0
int Router::faceXY(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y) {
	uint8 target_dir = 0;

	// If this is the start of the turn, get the mega's current feet
	// coords + the required direction

	ObjectLogic obLogic(ob_logic);

	if (obLogic.getLooping() == 0) {
		ObjectMega obMega(ob_mega);

		target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), target_x, target_y);
	}

	return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
}
예제 #2
0
int Router::walkToTalkToMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId, uint32 separation) {
	ObjectMega obMega(ob_mega);

	int16 target_x = 0;
	int16 target_y = 0;
	uint8 target_dir = 0;

	// If this is the start of the walk, calculate the route.

	ObjectLogic obLogic(ob_logic);

	if (obLogic.getLooping() == 0) {
		assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);

		// Call the base script. This is the graphic/mouse service
		// call, and will set _engineMega to the ObjectMega of mega we
		// want to route to.

		_vm->_logic->runResScript(megaId, 3);

		ObjectMega targetMega(_vm->_logic->getEngineMega());

		// Stand exactly beside the mega, ie. at same y-coord
		target_y = targetMega.getFeetY();

		int scale = obMega.calcScale();
		int mega_separation = (separation * scale) / 256;

		debug(4, "Target is at (%d, %d), separation %d", targetMega.getFeetX(), targetMega.getFeetY(), mega_separation);

		if (targetMega.getFeetX() < obMega.getFeetX()) {
			// Target is left of us, so aim to stand to their
			// right. Face down_left

			target_x = targetMega.getFeetX() + mega_separation;
			target_dir = 5;
		} else {
			// Ok, must be right of us so aim to stand to their
			// left. Face down_right.

			target_x = targetMega.getFeetX() - mega_separation;
			target_dir = 3;
		}
	}

	return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
}
예제 #3
0
파일: anims.cpp 프로젝트: AReim1982/scummvm
int Router::megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse) {
	int32 animRes = 0;

	// If this is the start of the anim, read the anim table to get the
	// appropriate anim resource

	ObjectLogic obLogic(ob_logic);

	if (obLogic.getLooping() == 0) {
		ObjectMega obMega(ob_mega);

		// Appropriate anim resource is in 'table[direction]'
		animRes = READ_LE_UINT32(animTable + 4 * obMega.getCurDir());
	}

	return doAnimate(ob_logic, ob_graph, animRes, reverse);
}
예제 #4
0
void Router::standAt(byte *ob_graph, byte *ob_mega, int32 x, int32 y, int32 dir) {
	assert(dir >= 0 && dir <= 7);

	ObjectGraphic obGraph(ob_graph);
	ObjectMega obMega(ob_mega);

	// Set up the stand frame & set the mega's new direction

	obMega.setFeetX(x);
	obMega.setFeetY(y);
	obMega.setCurDir(dir);

	// Mega-set animation file
	obGraph.setAnimResource(obMega.getMegasetRes());

	// Dir + first stand frame (always frame 96)
	obGraph.setAnimPc(dir + 96);
}
예제 #5
0
int Router::doFace(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint8 target_dir) {
	int16 target_x = 0;
	int16 target_y = 0;

	// If this is the start of the turn, get the mega's current feet
	// coords + the required direction

	ObjectLogic obLogic(ob_logic);

	if (obLogic.getLooping() == 0) {
		assert(target_dir <= 7);

		ObjectMega obMega(ob_mega);

		target_x = obMega.getFeetX();
		target_y = obMega.getFeetY();
	}

	return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
}
예제 #6
0
int Router::faceMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId) {
	uint8 target_dir = 0;

	// If this is the start of the walk, decide where to walk to.

	ObjectLogic obLogic(ob_logic);

	if (obLogic.getLooping() == 0) {
		assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);

		// Call the base script. This is the graphic/mouse service
		// call, and will set _engineMega to the ObjectMega of mega we
		// want to turn to face.

		_vm->_logic->runResScript(megaId, 3);

		ObjectMega obMega(ob_mega);
		ObjectMega targetMega(_vm->_logic->getEngineMega());

		target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), targetMega.getFeetX(), targetMega.getFeetY());
	}

	return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
}
예제 #7
0
uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
	Common::MemoryReadStream readS(buffer, size);

	// Calc checksum & check that aginst the value stored in the header

	if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
		free(buffer);
		return SR_ERR_INCOMPATIBLE;
	}

	readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);

	// Check savegame against length of current global variables resource
	// This would most probably be trapped by the checksum test anyway,
	// but it doesn't do any harm to check this as well.

	// Historical note: During development, earlier savegames would often
	// be shorter than the current expected length.

	if (readS.readUint32LE() != _resman->fetchLen(1)) {
		free(buffer);
		return SR_ERR_INCOMPATIBLE;
	}

	byte *globalVars = _resman->openResource(1);
	byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();

	uint32 screenId = readS.readUint32LE();
	uint32 runListId = readS.readUint32LE();
	uint32 feetX = readS.readUint32LE();
	uint32 feetY = readS.readUint32LE();
	uint32 musicId = readS.readUint32LE();

	// Trash all resources from memory except player object & global vars
	_resman->killAll(false);
	_logic->resetKillList();

	readS.read(objectHub, ObjectHub::size());
	readS.read(_logic->_saveLogic, ObjectLogic::size());
	readS.read(_logic->_saveGraphic, ObjectGraphic::size());
	readS.read(_logic->_saveMega, ObjectMega::size());

	// Fill out the player object structures from the savegame structures.
	// Also run the appropriate scripts to set up George's anim tables and
	// walkdata, and Nico's anim tables.

	// Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
	_logic->runResScript(CUR_PLAYER_ID, 8);

	// Script no. 14 - 'set_up_nico_anim_tables'
	_logic->runResScript(CUR_PLAYER_ID, 14);

	// Which megaset was the player at the time of saving?
	ObjectMega obMega(_logic->_saveMega);

	uint32 scriptNo = 0;

	switch (obMega.getMegasetRes()) {
	case 36:		// GeoMega:
		scriptNo = 9;	// script no.9	- 'player_is_george'
		break;
	case 2003:		// GeoMegaB:
		scriptNo = 13;	// script no.13 - 'player_is_georgeB'
		break;
	case 1366:		// NicMegaA:
		scriptNo = 11;	// script no.11 - 'player_is_nicoA'
		break;
	case 1437:		// NicMegaB:
		scriptNo = 12;	// script no.12 - 'player_is_nicoB'
		break;
	case 1575:		// NicMegaC:
		scriptNo = 10;	// script no.10 - 'player_is_nicoC'
		break;
	}

	_logic->runResScript(CUR_PLAYER_ID, scriptNo);

	// Copy variables from savegame buffer to memory
	readS.read(globalVars, _resman->fetchLen(1));

	_resman->closeResource(CUR_PLAYER_ID);
	_resman->closeResource(1);

	free(buffer);

	int32 pars[2];

	pars[0] = screenId;
	pars[1] = 1;
	_logic->fnInitBackground(pars);

	ScreenInfo *screenInfo = _screen->getScreenInfo();

	// So palette not restored immediately after control panel - we want to
	// fade up instead!
	screenInfo->new_palette = 99;

	// These need setting after the defaults get set in fnInitBackground.
	// Remember that these can change through the game, so need saving &
	// restoring too.

	screenInfo->feet_x = feetX;
	screenInfo->feet_y = feetY;

	// Start the new run list
	_logic->expressChangeSession(runListId);

	// Force in the new scroll position, so unsightly scroll-catch-up does
	// not occur when screen first draws after returning from restore panel

	// Set the screen record of player position - ready for setScrolling()

	screenInfo->player_feet_x = obMega.getFeetX();
	screenInfo->player_feet_y = obMega.getFeetY();

	// if this screen is wide, recompute the scroll offsets now
	if (screenInfo->scroll_flag)
		_screen->setScrolling();

	// Any music required will be started after we've returned from
	// restoreControl() - see systemMenuMouse() in mouse.cpp!

	// Restart any looping music. Originally this was - and still is - done
	// in systemMenuMouse(), but with ScummVM we have other ways of
	// restoring savegames so it's easier to put it here as well.

	if (musicId) {
		pars[0] = musicId;
		pars[1] = FX_LOOP;
		_logic->fnPlayMusic(pars);
	} else
		_logic->fnStopMusic(NULL);

	return SR_OK;
}
예제 #8
0
void Logic::locateTalker(int32 *params) {
	// params:	0 pointer to ob_graphic
	//		1 pointer to ob_speech
	//		2 pointer to ob_logic
	//		3 pointer to ob_mega
	//		4 encoded text number
	//		5 wav res id
	//		6 anim res id
	//		7 pointer to anim table
	//		8 animation mode	0 lip synced,
	//					1 just straight animation

	if (!_animId) {
		// There is no animation. Assume it's voice-over text, and put
		// it at the bottom of the screen.

		_textX = 320;
		_textY = 400;
		return;
	}

	byte *file = _vm->_resman->openResource(_animId);

	// '0' means 1st frame

	CdtEntry cdt_entry;
	FrameHeader frame_head;

	cdt_entry.read(_vm->fetchCdtEntry(file, 0));
	frame_head.read(_vm->fetchFrameHeader(file, 0));

	// Note: This part of the code is quite similar to registerFrame().

	if (cdt_entry.frameType & FRAME_OFFSET) {
		// The frame has offsets, i.e. it's a scalable mega frame
		ObjectMega obMega(decodePtr(params[S_OB_MEGA]));

		uint16 scale = obMega.calcScale();

		// Calc suitable centre point above the head, based on scaled
		// height

		// just use 'feet_x' as centre
		_textX = obMega.getFeetX();

		// Add scaled y-offset to feet_y coord to get top of sprite
		_textY = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
	} else {
		// It's a non-scaling anim - calc suitable centre point above
		// the head, based on scaled width

		// x-coord + half of width
		_textX = cdt_entry.x + frame_head.width / 2;
		_textY = cdt_entry.y;
	}

	_vm->_resman->closeResource(_animId);

	// Leave space above their head
	_textY -= GAP_ABOVE_HEAD;

	// Adjust the text coords for RDSPR_DISPLAYALIGN

	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();

	_textX -= screenInfo->scroll_offset_x;
	_textY -= screenInfo->scroll_offset_y;
}
예제 #9
0
void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) {
	ObjectGraphic obGraph(ob_graph);
	ObjectMega obMega(ob_mega);

	assert(obGraph.getAnimResource());

	byte *file = _vm->_resman->openResource(obGraph.getAnimResource());

	AnimHeader anim_head;
	CdtEntry cdt_entry;
	FrameHeader frame_head;

	anim_head.read(_vm->fetchAnimHeader(file));
	cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc()));
	frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc()));

	// update player graphic details for on-screen debug info
	if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
		_vm->_debugger->_graphType = obGraph.getType();
		_vm->_debugger->_graphAnimRes = obGraph.getAnimResource();
		// counting 1st frame as 'frame 1'
		_vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1;
		_vm->_debugger->_graphNoFrames = anim_head.noAnimFrames;
	}

	// fill in the BuildUnit structure for this frame

	build_unit->anim_resource = obGraph.getAnimResource();
	build_unit->anim_pc = obGraph.getAnimPc();
	build_unit->layer_number = 0;

	// Affected by shading mask?
	if (obGraph.getType() & SHADED_SPRITE)
		build_unit->shadingFlag = true;
	else
		build_unit->shadingFlag = false;

	// Check if this frame has offsets ie. this is a scalable mega frame

	int scale = 0;

	if (cdt_entry.frameType & FRAME_OFFSET) {
		scale = obMega.calcScale();

		// calc final render coordinates (top-left of sprite), based
		// on feet coords & scaled offsets

		// add scaled offsets to feet coords
		build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256;
		build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256;

		// Work out new width and height. Always divide by 256 after
		// everything else, to maintain accurary
		build_unit->scaled_width = ((scale * frame_head.width) / 256);
		build_unit->scaled_height = ((scale * frame_head.height) / 256);
	} else {
		// It's a non-scaling anim. Get render coords for sprite, from cdt
		build_unit->x = cdt_entry.x;
		build_unit->y = cdt_entry.y;

		// Get width and height
		build_unit->scaled_width = frame_head.width;
		build_unit->scaled_height = frame_head.height;
	}

	// either 0 or required scale, depending on whether 'scale' computed
	build_unit->scale = scale;

	// calc the bottom y-coord for sorting purposes
	build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;

	if (ob_mouse) {
		// passed a mouse structure, so add to the _mouseList
		_vm->_mouse->registerMouse(ob_mouse, build_unit);

	}

	_vm->_resman->closeResource(obGraph.getAnimResource());
}
예제 #10
0
int Router::doWalk(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir) {
	ObjectLogic obLogic(ob_logic);
	ObjectGraphic obGraph(ob_graph);
	ObjectMega obMega(ob_mega);

	// If this is the start of the walk, calculate the route.

	if (obLogic.getLooping() == 0) {
		// If we're already there, don't even bother allocating
		// memory and calling the router, just quit back & continue
		// the script! This avoids an embarassing mega stand frame
		// appearing for one cycle when we're already in position for
		// an anim eg. repeatedly clicking on same object to repeat
		// an anim - no mega frame will appear in between runs of the
		// anim.

		if (obMega.getFeetX() == target_x && obMega.getFeetY() == target_y && obMega.getCurDir() == target_dir) {
			_vm->_logic->writeVar(RESULT, 0);
			return IR_CONT;
		}

		assert(target_dir <= 8);

		obMega.setWalkPc(0);

		// Set up mem for _walkData in route_slots[] & set mega's
		// 'route_slot_id' accordingly
		allocateRouteMem();

		int32 route = routeFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);

		// 0 = can't make route to target
		// 1 = created route
		// 2 = zero route but may need to turn

		if (route != 1 && route != 2) {
			freeRouteMem();
			_vm->_logic->writeVar(RESULT, 1);
			return IR_CONT;
		}

		// Walk is about to start

		obMega.setIsWalking(1);
		obLogic.setLooping(1);
		obGraph.setAnimResource(obMega.getMegasetRes());
	} else if (_vm->_logic->readVar(EXIT_FADING) && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
		// Double clicked an exit, and the screen has faded down to
		// black. Ok, that's it. Back to script and change screen.

		// We have to clear te EXIT_CLICK_ID variable in case there's a
		// walk instruction on the new screen, or it'd be cut short.

		freeRouteMem();

		obLogic.setLooping(0);
		obMega.setIsWalking(0);
		_vm->_logic->writeVar(EXIT_CLICK_ID, 0);
		_vm->_logic->writeVar(RESULT, 0);

		return IR_CONT;
	}

	// Get pointer to walkanim & current frame position

	WalkData *walkAnim = getRouteMem();
	int32 walk_pc = obMega.getWalkPc();

	// If stopping the walk early, overwrite the next step with a
	// slow-out, then finish

	if (_vm->_logic->checkEventWaiting() && walkAnim[walk_pc].step == 0 && walkAnim[walk_pc + 1].step == 1) {
		// At the beginning of a step
		earlySlowOut(ob_mega, ob_walkdata);
	}

	// Get new frame of walk

	obGraph.setAnimPc(walkAnim[walk_pc].frame);
	obMega.setCurDir(walkAnim[walk_pc].dir);
	obMega.setFeetX(walkAnim[walk_pc].x);
	obMega.setFeetY(walkAnim[walk_pc].y);

	// Is the NEXT frame is the end-marker (512) of the walk sequence?

	if (walkAnim[walk_pc + 1].frame != 512) {
		// No, it wasn't. Increment the walk-anim frame number and
		// come back next cycle.
		obMega.setWalkPc(obMega.getWalkPc() + 1);
		return IR_REPEAT;
	}

	// We have reached the end-marker, which means we can return to the
	// script just as the final (stand) frame of the walk is set.

	freeRouteMem();
	obLogic.setLooping(0);
	obMega.setIsWalking(0);

	// If George's walk has been interrupted to run a new action script for
	// instance or Nico's walk has been interrupted by player clicking on
	// her to talk

	// There used to be code here for checking if two megas were colliding,
	// but it had been commented out, and it was only run if a function
	// that always returned zero returned non-zero.

	if (_vm->_logic->checkEventWaiting()) {
		_vm->_logic->startEvent();
		_vm->_logic->writeVar(RESULT, 1);
		return IR_TERMINATE;
	}

	_vm->_logic->writeVar(RESULT, 0);

	// CONTINUE the script so that RESULT can be checked! Also, if an anim
	// command follows the fnWalk command, the 1st frame of the anim (which
	// is always a stand frame itself) can replace the final stand frame of
	// the walk, to hide the slight difference between the shrinking on the
	// mega frames and the pre-shrunk anim start-frame.

	return IR_CONT;
}