diff options
| author | Max Horn | 2002-08-21 16:07:07 +0000 | 
|---|---|---|
| committer | Max Horn | 2002-08-21 16:07:07 +0000 | 
| commit | ce46866403fdcc479cf9d67e4d430409b15dadc3 (patch) | |
| tree | 75ebfaa1ed13f549959d76d3ce101c3e66f5451b /simon/verb.cpp | |
| parent | 662256f25dbe43abf67077a804e225738765f009 (diff) | |
| download | scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.gz scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.bz2 scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.zip | |
Initial revision
svn-id: r4785
Diffstat (limited to 'simon/verb.cpp')
| -rw-r--r-- | simon/verb.cpp | 449 | 
1 files changed, 449 insertions, 0 deletions
| diff --git a/simon/verb.cpp b/simon/verb.cpp new file mode 100644 index 0000000000..a81627bff2 --- /dev/null +++ b/simon/verb.cpp @@ -0,0 +1,449 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001/2002 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * $Header$ + * + */ + +// Verb and hitarea handling +#include "stdafx.h" +#include "simon/simon.h" +#include "simon/intern.h" + +void SimonState::defocusHitarea() +{ +	HitArea *last; +	HitArea *ha; + +	if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2DOS)) { +		if (_bit_array[4] & 0x8000) { +			o_unk_120(202); +			_last_hitarea_2_ptr = NULL; +			return; +		} +	} + +	last = _hitarea_ptr_5; + +	if (last == _hitarea_ptr_7) +		return; + +	hitareaChangedHelper(); +	_hitarea_ptr_7 = last; + +	if (last != NULL && _hitarea_unk_6 && +			(ha = findHitAreaByID(200)) && (ha->flags & 0x40) && !(last->flags & 0x40)) +		focusVerb(last->id); +} + +static const char *const verb_names[] = { +	"Walk to", +	"Look at", +	"Open", +	"Move", + +	"Consume", +	"Pick up", +	"Close", +	"Use", + +	"Talk to", +	"Remove", +	"Wear", +	"Give" +}; + +static const char *const verb_prep_names[] = { +	"", "", "", "", +	"", "", "", "with what ?", +	"", "", "", "to whom ?" +}; + +void SimonState::focusVerb(uint hitarea_id) +{ +	uint x; +	const char *txt; + +	hitarea_id -= 101; + +	CHECK_BOUNDS(hitarea_id, verb_prep_names); + +	if (_show_preposition) { +		txt = verb_prep_names[hitarea_id]; +	} else { +		txt = verb_names[hitarea_id]; +	} +	x = (53 - strlen(txt)) * 3; +	showActionString(x, (const byte *)txt); + +} + +void SimonState::showActionString(uint x, const byte *string) +{ +	FillOrCopyStruct *fcs; + +	fcs = _fcs_ptr_array_3[1]; +	if (fcs == NULL || fcs->text_color == 0) +		return; + +	fcs->textColumn = x >> 3; +	fcs->textColumnOffset = x & 7; + +	for (; *string; string++) +		video_putchar(fcs, *string); +} + + +void SimonState::hitareaChangedHelper() +{ +	FillOrCopyStruct *fcs; + +	if ((_game == GAME_SIMON2WIN) || (_game == GAME_SIMON2WIN)) { +		if (_bit_array[4] & 0x8000) +			return; +	} + +	fcs = _fcs_ptr_array_3[1]; +	if (fcs != NULL && fcs->text_color != 0) +		video_fill_or_copy_from_3_to_2(fcs); + +	_last_hitarea_2_ptr = NULL; +	_hitarea_ptr_7 = NULL; +} + +HitArea *SimonState::findHitAreaByID(uint hitarea_id) +{ +	HitArea *ha = _hit_areas; +	uint count = ARRAYSIZE(_hit_areas); + +	do { +		if (ha->id == hitarea_id) +			return ha; +	} while (ha++, --count); +	return NULL; +} + +HitArea *SimonState::findEmptyHitArea() +{ +	HitArea *ha = _hit_areas; +	uint count = ARRAYSIZE(_hit_areas); + +	do { +		if (ha->flags == 0) +			return ha; +	} while (ha++, --count); +	return NULL; +} + +void SimonState::clear_hitarea_bit_0x40(uint hitarea) +{ +	HitArea *ha = findHitAreaByID(hitarea); +	if (ha != NULL) +		ha->flags &= ~0x40; +} + +void SimonState::set_hitarea_bit_0x40(uint hitarea) +{ +	HitArea *ha = findHitAreaByID(hitarea); +	if (ha != NULL) { +		ha->flags |= 0x40; +		ha->flags &= ~2; +		if (hitarea == 102) +			hitarea_proc_1(); +	} +} + +void SimonState::set_hitarea_x_y(uint hitarea, int x, int y) +{ +	HitArea *ha = findHitAreaByID(hitarea); +	if (ha != NULL) { +		ha->x = x; +		ha->y = y; +	} +} + +void SimonState::delete_hitarea(uint hitarea) +{ +	HitArea *ha = findHitAreaByID(hitarea); +	if (ha != NULL) { +		ha->flags = 0; +		if (ha == _last_hitarea_2_ptr) +			defocusHitarea(); +		_need_hitarea_recalc++; +	} +} + +bool SimonState::is_hitarea_0x40_clear(uint hitarea) +{ +	HitArea *ha = findHitAreaByID(hitarea); +	if (ha == NULL) +		return false; +	return (ha->flags & 0x40) == 0; +} + +void SimonState::addNewHitArea(int id, int x, int y, int width, int height, +															 int flags, int unk3, Item *item_ptr) +{ + +	HitArea *ha; +	delete_hitarea(id); + +	ha = findEmptyHitArea(); +	ha->x = x; +	ha->y = y; +	ha->width = width; +	ha->height = height; +	ha->flags = flags | 0x20; +	ha->id = ha->layer = id; +	ha->unk3 = unk3; +	ha->item_ptr = item_ptr; + +	_need_hitarea_recalc++; +} + +void SimonState::hitarea_proc_1() +{ +	uint id; +	HitArea *ha; + +	if (_game & GAME_SIMON2) { +		id = 2; +		if (!(_bit_array[4] & 0x8000)) +			id = (_mouse_y >= 136) ? 102 : 101; +	} else { +		id = (_mouse_y >= 136) ? 102 : 101; + +	} + +	_hitarea_unk_4 = id; + +	ha = findHitAreaByID(id); +	if (ha == NULL) +		return; + +	if (ha->flags & 0x40) { +		_hitarea_unk_4 = 999; +		_hitarea_ptr_5 = NULL; +	} else { +		_verb_hitarea = ha->unk3; +		handle_verb_hitarea(ha); +	} +} + +void SimonState::handle_verb_hitarea(HitArea * ha) +{ +	HitArea *tmp = _hitarea_ptr_5; + +	if (ha == tmp) +		return; + +	if (!(_game & GAME_SIMON2)) { +		if (tmp != NULL) { +			tmp->flags |= 8; +			video_toggle_colors(tmp, 0xd5, 0xd0, 0xd5, 0xA); +		} + +		if (ha->flags & 2) +			video_toggle_colors(ha, 0xda, 0xd5, 0xd5, 5); +		else +			video_toggle_colors(ha, 0xdf, 0xda, 0xda, 0xA); + +		ha->flags &= ~(2 + 8); + +	} else { +		if (ha->id < 101) +			return; +		_mouse_cursor = ha->id - 101; +		_need_hitarea_recalc++; + +	} + +	_hitarea_ptr_5 = ha; +} + +void SimonState::hitarea_leave(HitArea * ha) +{ +	if (!(_game & GAME_SIMON2)) { +		video_toggle_colors(ha, 0xdf, 0xd5, 0xda, 5); +	} else { +		video_toggle_colors(ha, 0xe7, 0xe5, 0xe6, 1); +	} +} + +void SimonState::leaveHitAreaById(uint hitarea_id) +{ +	HitArea *ha = findHitAreaByID(hitarea_id); +	if (ha) +		hitarea_leave(ha); +} + +void SimonState::handle_unk2_hitarea(FillOrCopyStruct *fcs) +{ +	uint index; + +	index = get_fcs_ptr_3_index(fcs); + +	if (fcs->fcs_data->unk1 == 0) +		return; + +	lock(); +	fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, fcs->fcs_data->unk1 - 1, fcs->fcs_data->unk2); +	unlock(); +} + +void SimonState::handle_unk_hitarea(FillOrCopyStruct *fcs) +{ +	uint index; + +	index = get_fcs_ptr_3_index(fcs); + +	lock(); +	fcs_unk_proc_1(index, fcs->fcs_data->item_ptr, fcs->fcs_data->unk1 + 1, fcs->fcs_data->unk2); +	unlock(); +} + +void SimonState::setup_hitarea_from_pos(uint x, uint y, uint mode) +{ +	HitArea *best_ha; + +	if (_game & GAME_SIMON2) { +		if (_bit_array[4] & 0x8000 || y < 134) { +			x += _x_scroll * 8; +		} +	} + +	{ +		HitArea *ha = _hit_areas; +		uint count = ARRAYSIZE(_hit_areas); +		uint16 layer = 0; +		const uint16 x_ = x; +		const uint16 y_ = y; + +		best_ha = NULL; + +		do { +			if (ha->flags & 0x20) { +				if (!(ha->flags & 0x40)) { +					if (x_ >= ha->x && y_ >= ha->y && +							x_ - ha->x < ha->width && y_ - ha->y < ha->height && layer <= ha->layer) { +						layer = ha->layer; +						best_ha = ha; +					} else { +						if (ha->flags & 2) { +							hitarea_leave(ha); +							ha->flags &= ~2; +						} +					} +				} else { +					ha->flags &= ~2; +				} +			} +		} while (ha++, --count); +	} + +	if (best_ha == NULL) { +		defocusHitarea(); +		return; +	} + +	if (mode != 0 && mode != 3) { +		_last_hitarea = best_ha; +		_variableArray[1] = x; +		_variableArray[2] = y; +	} + +	if (best_ha->flags & 4) { +		defocusHitarea(); +	} else if (best_ha != _last_hitarea_2_ptr) { +		new_current_hitarea(best_ha); +	} + +	if (best_ha->flags & 8 && !(best_ha->flags & 2)) { +		hitarea_leave(best_ha); +		best_ha->flags |= 2; +	} + +	return; +} + +void SimonState::new_current_hitarea(HitArea * ha) +{ +	bool result; + +	hitareaChangedHelper(); +	if (ha->flags & 1) { +		result = hitarea_proc_2(ha->flags >> 8); +	} else { +		result = hitarea_proc_3(ha->item_ptr); +	} + +	if (result) +		_last_hitarea_2_ptr = ha; +} + +bool SimonState::hitarea_proc_2(uint a) +{ +	uint x; +	const byte *string_ptr; + +	if (_game & GAME_SIMON2) { +		if (_bit_array[4] & 0x8000) { +			Subroutine *sub; +			_variableArray[84] = a; +			sub = getSubroutineByID(5003); +			if (sub != NULL) +				startSubroutineEx(sub); +			return true; +		} +	} + +	if (a >= 20) +		return false; + +	string_ptr = getStringPtrByID(_stringid_array_2[a]); +	// Arisme : hack for long strings in the French version +	if ((strlen((const char*)string_ptr) - 1) <= 53) +		x = (53 - (strlen((const char *)string_ptr) - 1)) * 3; +	else +		x = 0; +	showActionString(x, string_ptr); + +	return true; +} + +bool SimonState::hitarea_proc_3(Item *item) +{ +	Child2 *child2; +	uint x; +	const byte *string_ptr; + +	if (item == 0 || item == _dummy_item_2 || item == _dummy_item_3) +		return false; + +	child2 = findChildOfType2(item); +	if (child2 == NULL) +		return false; + +	string_ptr = getStringPtrByID(child2->string_id); +	// Arisme : hack for long strings in the French version +	if ((strlen((const char*)string_ptr) - 1) <= 53) +		x = (53 - (strlen((const char *)string_ptr) - 1)) * 3; +	else +		x = 0; +	showActionString(x, string_ptr); +	return true; +} | 
