Adventure Land — The Code MMORPG

Автор: | 10 января, 2022
Поделиться...

Долго размышлял, но всё таки взял себе игру Adventure Land — The Code MMORPG — игра, в которой, кроме всего прочего можно и нужно программировать поведение персонажа. Да ещё и не одного, а целых трёх боевых и одного торговца. А ведь игра появилась ещё где-то в 2017 году, вроде как…

Игра для программистов и как результат — я не мог пройти мимо неё.

Adventure Land - The Code MMORPG on Steam

В качестве языка программирования используется язык на основе JAVA. Что, в принципе, является и вариацией обучения программированию.

Adventure Land Análisis - Plaza MMO

Из основных минусов — исключительно англофицированное сообщество и минимальная документация.

Из странных плюсов — возможность запуска клиента практически на любой технике (даже на вишенках). Так как клиент работает и в браузерах с поддержкой JAVA. Вот, например, в данный момент у меня запущен воин из STEAM библиотеки, а маг и хиллер из Google Chrome. Но тут же есть и минусы:

  • При запуске из STEAM — клиент отжирает довольно не плохо ресурсы ПК
  • При запуске из браузера — клиенты «тормозят», т.к. выделяет им ресурсы браузер из собственных соображений

Ещё один плюс, можно входить с разных устройств одновременно одним и тем же героем. Тогда все «новые» подключения становятся наблюдателями.

Первое впечатление — весьма положительное. И даже за пару ночей сумел сделать нечто похожее на автоматизированный фарм голды с ближних монстриков.

Adventure Land - The Code MMORPG в Steam

Естественно, команда из троих — воин, маг и хиллер. Всё в лучших традициях MMO RPG.

Относительно рабочий код прикладываю (в данный момент он и занимается фармом):

// true - будет атаковать
// false - не будет воевать
var attack_mode=true;

var myOwner = character.owner; //": "5728172030558208",
var TANK
var DAMAGER
var HEALER
var myType

function isType(character){
	switch (character.type){
		case "priest": 
			mType = "Healer";
			break;
		case "warrior":
		case "paladin":
			mType = "Tank";
			break;
		case "merchant": // ???
			mType = "Merch";
			break;
		default:
			mType = "Damager";
			break;
	}
	return mType;
}

//game_log(get_characters());
//game_log(get_active_characters());

setInterval(function(){
	// ДЛЯ ВСЕХ ПЕРСОНАЖЕЙ - НАЧАЛО

	// перебор всех персонажей
	//show_json(get_characters());
	let obj = get_characters();
	for(key in obj){
		//log(key);
		if(obj[key].online != 0){
			tmp = isType(obj[key]);
			if (obj[key].name == character.name){
				myType = tmp;
			}

			if (tmp == "Tank"){
				TANK = obj[key].name;
			}
			if (tmp == "Damager"){
				DAMAGER = obj[key].name;
			}
			if (tmp == "Healer"){
				HEALER = obj[key].name;
			}
			//show_json(obj[key]);
			//log(obj[key].name + " is " + tmp);

		}
	}
	//log("My type: " + myType);
	
	// использовать зелья, когда нужно
	if(character.hp<character.max_hp/3 || character.mp<character.max_mp/3){
		use_hp_or_mp();
		//game_log(character.name + " use POTION...");
	} 	
	// подобрать лут
	loot();

	
	// ДЛЯ КАЖДОГО ТИПА
	switch (myType){
	case "Tank": 
		// принять party от хиллера
		x = get_party()
		if (!x[HEALER]){
			log("NOT IN PARTY");
			accept_party_request(HEALER)
			send_party_request(HEALER);
			// show_json(get_party());
		}

		// выйти если не атакую или мёртв или двигается
		if(!attack_mode || character.rip || is_moving(character)) return;

		var target=get_targeted_monster();
		if(!target)
		{
			target=get_nearest_monster({min_xp:100,max_att:120});
			if(target){
				change_target(target);
				//log(get_target());
			}
			else
			{
				set_message("No Monsters");
				return;
			}
		}
		
		if(!is_in_range(target)) // вне дистанции атаки
		{
			move( // сокращение дистанции на половину
				character.x+(target.x-character.x)/2,
				character.y+(target.y-character.y)/2
				);
		}
		else if(can_attack(target))	// могу атаковать?
		{
			set_message("Attacking");
			attack(target);
		}
		break;
		
	case "Damager":
		// принять party от хиллера
		x = get_party()
		if (!x[HEALER]){
			log("NOT IN PARTY");
			//accept_party_request(HEALER);
			accept_party_request(HEALER)
			send_party_request(HEALER);
			// show_json(get_party());
		}
			
		// выйти если не атакую или мёртв или двигается
		if(!attack_mode || character.rip || is_moving(character)) return;

			if(character.max_hp - character.hp > 200 ||
			   character.max_mp - character.mp > 300)
				use_hp_or_mp();
			
			// Party leader
			var leader = get_player(TANK);
			
			// Current target and target of leader.
			var currentTarget = get_targeted_monster();
			var leaderTarget = get_target_of(leader)
			
			// Change the target.
			if (!currentTarget || currentTarget != leaderTarget){ 
				// Current target is empty or other than the leader's.
				change_target(leaderTarget);
				currentTarget = get_targeted_monster();
			}
			
			// Attack the target.
			targetTarget = get_target_of(currentTarget)
			if(currentTarget && can_attack(currentTarget) && targetTarget == leader){
			// Current target isn't empty and attackable.
				attack(currentTarget);
			}
			//Move to leader.
			if(!character.moving){
				if(!is_in_range(leader)) // вне дистанции атаки
				{
					move( // сокращение дистанции на половину
						character.x+(leader.real_x-character.x)/2,
						character.y+( leader.real_y-character.y)/2
						);
				}
			}
	
		break;
	case "Healer":
		// проверить у напарников здоровье и вылечить их
	/*	if (TANK){
			targ = get_player(TANK)
			if(!targ.rip && targ.hp < targ.max_hp / 2){
				heal(targ);
			};
		};
		if (DAMAGER){
			targ = get_player(DAMAGER)
			if(!targ.rip && targ.hp < targ.max_hp / 2){
				heal(targ);
			};
		};
	*/	
			
		let ob = get_party();
		for(key in ob){
			//log(key);
			targ = get_player(key)
			hp = targ.hp
			mhp = targ.max_hp
			if (hp< mhp/2){
				heal(targ);
				log("Heal: " + key + " " + hp + "/" + mhp)
			}
		}			
		
		//Move to leader.
		// Party leader
		var leader = get_player(TANK);

		if(!character.moving){
			if(!is_in_range(leader)) // вне дистанции атаки
			{
				move( // сокращение дистанции на половину
					character.x+(leader.real_x-character.x)/2,
					character.y+( leader.real_y-character.y)/2
					);
			}
		}

		// хиллер собирает команду
		let obj = get_party();
		//log (obj);
		if( !obj[TANK] )
		{
			log("==TANK====================")
			//log(obj[TANK])
			send_party_request(TANK);
			accept_party_request(TANK)
		}
		if( !obj[DAMAGER] )
		{
			log("==DAMAG===================")
			//log(obj[DAMAGER])
			send_party_request(DAMAGER);
			accept_party_request(DAMAGER)
		}

		break;
	default: // Healer
			log("No logic for type: " + MyType);
		break;
	}

},1000/4); // повторяем каждые 1/4 секунды.

// событие после смерти
function handle_death()
{
	setTimeout(respawn,25000);
	return true;
	// This ensures you keep on farming, yet, to retain your XP, do enhance the logic for defense
}
// Learn Javascript: https://www.codecademy.com/learn/introduction-to-javascript
// Write your own CODE: https://github.com/kaansoral/adventureland

Ну вот, как то такое моё первое знакомство с игрой.

Ссылочки:

Советы новичкам

Первая

Вторая

Третья

Торгаш

Кайтинг

Список функций — почти с описанием


Поделиться...

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *