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; +} |