RU 📌 Pinned

Как сделать?

Dark[Ol(U23)leneri] #34 18.04.2010 22:57 6408 comments 2424004 views

Я использовал плеер 5.7, скачал последний 5.9.3, в нем все работает (моя вина). Но спасибо, всем! Простите, не заметил что форум ушёл на следующую страницу и только сейчас увидел ваши ответы (отвык от форумов).

Миша Поэт #1572 18.10.2025 19:05 (4 months ago)

Подскажите, пожалуйста

Правильно ли я понимаю, что я не могу сделать итерацию не по всему массиву, а по ячейке массива. То есть “многомерные” массивы по сути не совсем многомерные, это те же линейные массивы, только с кортежами в качестве индекса.

Например, я создаю массив

LOCAL Q_INDEX = 0
$QUESTS_TEXT[Q_INDEX] = "Иди туда, не знаю куда и принеси то, не знаю что"
LOCAL STEP_INDEX = 0
$QUESTS_STEPS[Q_INDEX, STEP_INDEX, "todo"] = "Идти туда, не знаю куда"
QUESTS_STEPS[Q_INDEX, STEP_INDEX, "done"] = 1
STEP_INDEX += 1
$QUESTS_STEPS[Q_INDEX, STEP_INDEX, "todo"] = "Принести то, не знаю что"
QUESTS_STEPS[Q_INDEX, STEP_INDEX, "done"] = 0

Я в таком случае не могу узнать сколько в QUESTS_STEPS[QUEST_INDEX] хранится элементов, и соответственно проитерироваться? Мне нужно хранить условно еще один массив для квестов, где для каждого квеста помнить сколько у него есть шагов, типа QUESTS_STEPS_COUNT[QUEST_INDEX] = 2. И тогда брать эту переменную и с помощью нее итерироваться?

Да, верно. Можно итерироваться по всему массиву (обойти вообще все элементы) или хранить число элементов в каком-то “измерении” отдельно.
Для упрощения работы можно создать специальные служебные локации и вызывать через @/@@, но это будет работать медленнее.

Альтернативный вариант (на мой взгляд он лучше) - хранить элементы измерений, по которым нужно итерироваться, в разных массивах.

Всем привет, может для ветеранов вопрос глупый, но объясните пожалуйста.

Допустим, есть описание локации. Есть действие “осмотреться”, которое в описание выводит пару строк о том, что происходит вокруг через *PL. Так вот, объясните пожалуйста, как сделать так, чтобы описание которое выдается после этого действия выводилось после основного текста, а не перед ним?

Gvozd229, привет, можно пример кода, или подробней описать? Просто любой текст выводится после основного текста по умолчанию.

Вполне себе #2722 06.12.2025 17:23 (2 months ago)

Gvozd229, а, что ты подразумеваешь под “основной текст”?
Все операторы идут друг за другом, так что любой следующий вывод следует за предыдущим в порядке появления в коде. Поэтому смотри порядок операторов.

Действия через ACt выводятся в отдельном окне (окно действий), и как-то комбинировать их с основным окном может только пользователь. Но можно действия оформить как ссылки внутри текста - ну и тогда располагать их как угодно относительно текстовых блоков. Пример - ‘<a href=“EXEC:любойисполняемыйкод”>НАЗВАНИЕ ДЕЙСТВИЯ</a>’

Вполне себе #2722 12.12.2025 18:12 (2 months ago)

mkir:

Действия через ACt выводятся в отдельном окне (окно действий), и как-то комбинировать их с основным окном может только пользователь.

Имярек немного за другое говорит. Любое Действие может выводить дополнительный текст и этот текст будет продолжением уже выведенного. У камрада отчего-то текст при выполнении Действия выводится перед основным текстом страницы (на сколько я понял из объяснений). Могу предположить, что код выглядит примерно так:

Act 'Новая строка': *P "Балаболка" 		
*P "Абракадабра и кадабра абра"

Я давно отказался от “Прямого” вывода текста в КуСПе. Я сначала полностью формирую строку и только потом вывожу. Если мне надо что-то убрать или добавить, то сначала “строка” будет переформатирована и только потом выведена. Что и как выводить передаю самому себе в виде аргумента. Это избавляет от огромного числа “киноляов”. Иногда строку формирую вообще динамически, вплоть до применяемых операторов и операндов. Перед каждым формированием и выводом ставлю Действие “Спасение”, чтобы при возникновении ошибки можно было вернуться в игру, а не “зависнуть в чистом поле”.
Примерно так - простейшее формирование (статическое) нужной строки:

[b]# Кузница[/b]
SHOWSTAT Off
Act 'Спасение': GT 'Домой' 		& !Создание Действия возврата на основную локацию
$FullStr=Func($CurrentLocation)		& !Получаем строку вывода (Приводить не буду, идет простой перебор в цикле и вывод по очереди формирования в зависимости от нужной локации
$FullStr				& !Вывод полученной строки

If $CurrentLocation='Снаряжение':
	Act 'Собрать инвентарь': Gs 'Get_Ammo_BlackSmith' & Gt 'Кузница' & !Выполняем действие (идет случайный подбор инвентаря) и возвращаемся на локацию
	Act 'Продавать  |  Улучшать' : $CurrentLocation='Снаряжение_Героя' & $CurrentAmmo='' & Gt 'Кузница' & !Выполняем действие (переходим к выбору снаряжения у ГГ) и возвращаемся на локацию
	Act 'Назад ': КПокупке=Off & Gt 'Домой'
End
If $CurrentLocation='Снаряжение_Героя':
	Act 'Покупать' : $CurrentLocation='Снаряжение' & КПокупке=On & $CurrentAmmo='' & Gt 'Кузница' & !Выполняем действие и возвращаемся на локацию
End
If $CurrentLocation='Апгрейд_Снаряжения':
	Act 'Покупать' : $CurrentLocation='Снаряжение_Кузни' & $CurrentAmmo='' & Gt 'Кузница' & !Выполняем действие и возвращаемся на локацию
	Act 'Назад' : $CurrentLocation='Снаряжение_Героя' & Gt 'Кузница'
End
Delact 'Спасение'		& !Удаление Действия (Код локации отработал правильно или не вызвал критической ошибки)
[b]--- Кузница ---[/b]

Визуально выглядит так:

Пример динамического формирования выводимого:

!Локация Создания персонажа
!SHOWACTS On 		& !Включаем окно Действий
Local $ResStr
Local $RaceStr
Local $NameLeft, $NameRight, $NameInput
Local $GenderLeft, $GenderRight
Local $RaceLeft, $RaceRight, $RaceReset
Local $PhotoLeft, $PhotoRight, $PhotoReset
Local $РостLeft, $РостRight

*Clr 				& !Чистим поле
CLA					& !Удаляем Действия
If $Args[0]='First': 	& !Формирование при "первом посещении" локации
	CopyArr 'Player','NPC'
	CopyArr 'Tempo','NPC'
	!@CopyRacePreset('Tempo','Player')  & !Копируем нужные предустановки
	GoPresets=On
	!@Случайный_Пресонаж(On, On, On)
	Player['Раса']=Rand(0,6)
	Player['НомерФото']=Rand(RaceSize[Player['Раса']])
	@CopyRacePreset('Player',$Race[Player['Раса']]+'_0')
	@CopyRacePreset('Player',$Race[Player['Раса']]+'_'+Player['НомерФото'])
	SHOWACTS On 			& !Открыть окно Действий
	PercSelected=Off	& !Результат выбора перков.
End

! Динамическое формирование нужных операторов.

$NameLeft="If Player[''НомерИмя'']<=0:
Player[''НомерИмя'']=ArrSize(''$''+$Race[Player[''Раса'']]+''_Имя'')-1
Else
Player[''НомерИмя'']-=1
End
$Player[''Имя'']=ArrItem(''$''+$Race[Player[''Раса'']]+''_Имя'',Player[''НомерИмя''])"
$NameRight="If Player[''НомерИмя'']>=ArrSize(''$''+$Race[Player[''Раса'']]+''_Имя'')-1:
Player[''НомерИмя'']=0
Else
Player[''НомерИмя'']+=1
End
$Player[''Имя'']=ArrItem(''$''+$Race[Player[''Раса'']]+''_Имя'',Player[''НомерИмя''])"

$NameInput="$RaceStr=Input(''Введите имя персонажа:'')
$RaceStr=$Replace($RaceStr, '' '')
If $RaceStr<>'''' and $RaceStr<>$Player[''Имя'']:
$Player[''Имя'']=$RaceStr
Player[''НомерИмя'']=-1
End"

$GenderLeft="If Player[''Гендер'']<=0 : Player[''Гендер'']=1 Else Player[''Гендер'']-=1"
$GenderRight="If Player[''Гендер'']>=1 : Player[''Гендер'']=0 Else Player[''Гендер'']+=1"

$RaceLeft="If Player[''Раса'']<=0 : Player[''Раса'']=6 Else Player[''Раса'']-=1"
$RaceRight="If Player[''Раса'']>=6:Player[''Раса'']=0 Else Player[''Раса'']+=1"
$RaceReset="If Player[''НомерФото'']>RaceSize[Player[''Раса'']]:Player[''НомерФото'']=1
@CopyRacePreset(''Player'',$Race[Player[''Раса'']]+''_0'')
If GoPresets=On : @CopyRacePreset(''Player'',$Race[Player[''Раса'']]+''_''+Player[''НомерФото''])
If Player[''НомерИмя'']>-1 : 
If Player[''НомерИмя'']>=ArrSize(''$''+$Race[Player[''Раса'']]+''_Имя'') : Player[''НомерИмя'']=ArrSize(''$''+$Race[Player[''Раса'']]+''_Имя'')-1
$Player[''Имя'']=ArrItem(''$''+$Race[Player[''Раса'']]+''_Имя'',Player[''НомерИмя''])
End"

$PhotoLeft="If Player[''НомерФото'']<=1:Player[''НомерФото'']=RaceSize[Player[''Раса'']] Else Player[''НомерФото'']-=1"
$PhotoRight="If Player[''НомерФото'']>=RaceSize[Player[''Раса'']]:Player[''НомерФото'']=1 Else Player[''НомерФото'']+=1"
$PhotoReset="If GoPresets=On : @CopyRacePreset(''Player'',$Race[Player[''Раса'']]+''_''+Player[''НомерФото''])"

! Формирование "строки" вывода
$ResStr=@Заголовок('Создание персонажа')
$ResStr+='<center><table width=1250 <<$AlignLeft>> border=0 cellspacing=0 cellpadding=0>'
	$ResStr+='<tr>'
		$ResStr+='<td width=400 <<$AlignLeft>>>'
			$ResStr+='<table width=300 <<$AlignLeft>> border=0 cellspacing=0 cellpadding=0>'
				$ResStr+='<tr>' & !Строка имени
					$ResStr+='<td width=60 <<$AlignCLeft>>>'
						$ResStr+='Имя:'
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCLeft>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$NameLeft>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GLeft.png" height=24></a>' 
					$ResStr+='</td>'
					$ResStr+='<td width=252 <<$AlignCenter>>>'
					$ResStr+='<a href="exec: Dynamic(''<<$NameInput>>'') & Gs(''Создание_Персонажа'')" >'
						If Player['НомерИмя']=-1 and  $Player['Имя']='???' :
							$ResStr+='Введите имя</a>'
						Else
							$ResStr+='<<$Player["Имя"]>></a>'
						End
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCRight>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$NameRight>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GRight.png" height=24></a>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
				$ResStr+='<tr>'	& !Строка Расы
					$ResStr+='<td width=60 <<$AlignCLeft>>>'
						$ResStr+='Раса:'
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCLeft>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$RaceLeft>>'') & Dynamic(''<<$RaceReset>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GLeft.png" height=24></a>'
					$ResStr+='</td>'
					$ResStr+='<td width=252 <<$AlignCenter>>>'
						$ResStr+='<<$RaceName[Player[''Раса'']]>>'
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCRight>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$RaceRight>>'') & Dynamic(''<<$RaceReset>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GRight.png" height=24></a>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
				$ResStr+='<tr>'	& !Строка Пол
					$ResStr+='<td width=60 <<$AlignCLeft>>>'
						$ResStr+='Пол:'
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCLeft>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$GenderLeft>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GLeft.png" height=24></a>'
					$ResStr+='</td>'
					$ResStr+='<td width=252 <<$AlignCenter>>>'
						$ResStr+=$Гендер[Player['Гендер']]
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCRight>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$GenderRight>>'') & Gs(''Создание_Персонажа'')"><img src=".\pic\GRight.png" height=24></a>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
				$ResStr+='<tr>' & !Пустая строка
					$ResStr+='<td>'
						!$ResStr+='<br>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
			....
      $ResStr+='Навык метательного оружия: <b><<Player[''НавыкНож'']+Бонус[''НавыкНож'']>></b><br><br>'
			...
		$ResStr+='</td>'
		$ResStr+='<td width=350 <<$AlignCenter>>>'  & !Вывод картинки
			$ResStr+='<table width=350 <<$AlignLeft>> border=0 cellspacing=0 cellpadding=0>'
				$ResStr+='<tr>'
					$ResStr+='<td width=350 <<$AlignCTop>>>'
						$ResStr+='<img src="<<@GetMidlPicture(Player[''Раса''],Player[''НомерФото''])>>" height=400>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
			$ResStr+='</table>'
			$ResStr+='<table width=200 <<$AlignCenter>> border=0 cellspacing=0 cellpadding=0>'
				$ResStr+='<tr>'
					$ResStr+='<td width=24 <<$AlignCLeft>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$PhotoLeft>>'') & Dynamic(''<<$PhotoReset>>'') & @Создание_Персонажа"><img src=".\pic\GLeft.png" height=24></a>'
					$ResStr+='</td>'
					$ResStr+='<td width=148 <<$AlignCenter>>>'
						$ResStr+='Выбор вида'
					$ResStr+='</td>'
					$ResStr+='<td width=24 <<$AlignCRight>>>'
						$ResStr+='<a href="exec: Dynamic(''<<$PhotoRight>>'') & Dynamic(''<<$PhotoReset>>'') & @Создание_Персонажа"><img src=".\pic\GRight.png" height=24></a>'
					$ResStr+='</td>'
				$ResStr+='</tr>'
			$ResStr+='</table>'
		$ResStr+='</td>'
	$ResStr+='</tr>'
$ResStr+='</table></center>'
$ResStr				& !Вывод полученной строки

Act 'Создать случайного персонажа': @Случайный_Пресонаж(GoPresets, On, On) & @SetBonus & @Создание_Персонажа
If PercSelected<>On : Act 'Перейти к выбору перков': Gt 'Выбор_Перков' Else Act 'Изменить выбор перков': Gt 'Выбор_Перков'
If $Player['Имя']<>'' and $Player['Имя']<>'???' and PercSelected=On and Бонус[BonusCount+1]<>0 and Бонус[BonusCount+2]<>0 and Бонус[BonusCount+3]<>0 :
	Act @Цвет('Принять выбор и играть',ЗЕЛ,'b'): @Персонаж_Создан & Gt 'Письмо'
Else
	Act @Цвет('Принять выбор и играть',СЕР):
		Local $MsgStr=''
		If $Player['Имя']='' or $Player['Имя']='???' : $MsgStr+='Не задано имя Пресонажа<br>'
		If PercSelected<>On : $MsgStr+='Не выбраны перки<br>' 
		If Бонус[BonusCount+1]=0 or Бонус[BonusCount+2]=0 or Бонус[BonusCount+3]=0 : $MsgStr+='Не выбраны cтартовые бонусы'
		Msg($MsgStr)
	End	
End

Выглядит примерно так:

При нажатии на любую ссылку происходит изменение значения и возврат на локацию с полным переформированием строки вывода… и так по кругу, пока не отработает Дейстивие “Принять и Играть”

Помогите, плиз, понять многомерные массивы. Я, возможно, глупая, но я так и не поняла для чего они. Я читала в справке о них, но так и не поняла. Пожалуйста, объясните зачем они нужны? Как их использовать? Для чего нужны значения, что находятся вместо номеров ячеек? Как их использовать?
Хотя, возможно, я пока замахнулась на слишком сложную тему для себя, поэтому не могу пока понять, но всё же хотелось бы хоть немного понять многомерные массивы

Многомерные массивы полезны в случае, когда какое-либо значение нужно связать не с одним значением, а с несколькими.
Например, если описание какого-то предмета зависит только от порядкового номера предмета (м.б. от его названия?), то это одномерный массив.
Если описание предмета зависит не только от номера предмета, а еще и от локации, где игрок находится, то это уже двухмерный массив (в этом случае предмет с одним порядковым номером может иметь разное описание в зависимости от локации).

Другой пример - у нас есть двухмерная карта с координатами. Тогда содержимое каждой ячейки будет зависеть от 2х координат - это двухмерный массив (как таблица).
Если добавить еще одно измерение (например, содержимое _каждой_ ячейки карты зависит от координаты Z или от другого обязательного параметра), то это будет 3х-мерный массив.
Измерений может быть много, главный критерий создавать их или нет - это от скольких/каких _обязательных_ параметров зависит значение каждого элемента массива.

В QSP с этим немного проще, т.к. в пределах одного массива одна ячейка может зависеть от любого числа параметров (какие-то значения могут быть для 1го, другие для 2х, и т.д.)

Использовать это просто - нужно вместо одного значения-индекса массива, указать несколько через запятую.
Установка значения:

$описание[x,y]='это описание для ячейки x,y'

Использование значения:

pl $описание[x,y]
! другой немного странный пример:
if $локация[x,y]='крыша': pl 'Вы находитесь на крыше высокого здания'

Значение ячейки может зависеть от значений разных типов:

$описание[x,y,$value]='это описание для ячейки по переменным x,y,$value'
$описание['test', x]='это описание для ячейки "test",x'

Конечно, в качестве индексов можно использовать значения из других массивов (то есть, не просто переменные/константы).

Вполне себе #2722 30.01.2026 12:36 (3 weeks ago)

ShadowX2,
На мой взгляд самый простой способ понять многомерный массив можно на примере шахматной доски.
Есть некая “Длина” и некая “Ширина”. В шахматах это буквы: A,B,C,D,E,F,G,H и цифры 1,2,3,4,5,6,7,8. Каждая ячейка может быть или черная или белая, и в каждой ячейке у тебя может был какая-то фигура или ячейка пустая.
Тогда, классическая форма многомерного шахматного массива в КуСПе будет выглядеть примерно так (Условно):

$Доска['A',1,'Фигура']=$ЛадьяБел[1]
$Доска['A',1,'Цвет']='Черный'
$Доска['B',1,'Фигура']=$КоньБел[1] 
$Доска['B',1,'Цвет']='Белый'
$Доска['С',1,'Фигура']=$СлонБел['Черный'] 
$Доска['C',1,'Цвет']='Черный'
$Доска['D',1,'Фигура']=$ФерзьБел 
$Доска['D',1,'Цвет']='Белый'
$Доска['E',1,'Фигура']=$КорольБел 
$Доска['E',1,'Цвет']='Черный'
$Доска['F',1,'Фигура']=$СлонБел['Белый'] 
$Доска['F',1,'Цвет']='Белый'
$Доска['G',1,'Фигура']=$КоньБел[2] 
$Доска['G',1,'Цвет']='Черный'
$Доска['H',1,'Фигура']=$ЛадьяБел[2]
$Доска['H',1,'Цвет']='Белый'
....
$Доска['A',8,'Фигура']=$ЛадьяЧерн[1]
$Доска['A',8,'Цвет']='Белый'
$Доска['B',8,'Фигура']=$КоньЧерн[1] 
$Доска['B',8,'Цвет']='Черный'
$Доска['С',8,'Фигура']=$СлонЧерн['Белый'] 
$Доска['C',8,'Цвет']='Белый'
$Доска['D',8,'Фигура']=$ФерзьЧерн 
$Доска['D',8,'Цвет']='Черный'
$Доска['E',8,'Фигура']=$КорольЧерн 
$Доска['E',8,'Цвет']='Белый'
$Доска['F',8,'Фигура']=$СлонЧерн['Черный'] 
$Доска['F',8,'Цвет']='Черный'
$Доска['G',8,'Фигура']=$КоньЧерн[2] 
$Доска['G',8,'Цвет']='Белый'
$Доска['H',8,'Фигура']=$ЛадьяЧерн[2]
$Доска['H',8,'Цвет']='Черный'

Лично я стараюсь не использовать многомереки без необходимости. А разбиваю их на понятные одномерные, так проще воспринимать код.
Но, например, если некий предмет способен “переезжать” с локации на локацию и в пределах локации менять свое положение и оставаться там, пока кто-то не переместит его на другую, то в таких случаях можно хранить положение предмета в двумерном массиве.
Опять таки, надо понимать, что и как хранить. Мне проще хранить местонахождение предмета в свойствах самого предмета, или через динамический массив, где индекс массива - код предмета, а значение - локация. При больших массивах данных я привык пользоваться индексами. Каждый предмет, локация, непись (при необходимости) имеет свой уникальный индекс и через этот индекс они связываются.
Обычно я делаю функции-прокладки, которые могут из общего массива данных найти нужное и в любом количестве. Например для “Снаряжения” - по ID “Владельца” найти все Снаряжение, которое принадлежит данному Владельцу.

Доброго времени суток. Такой странный вопрос по предметам, а конкретно по $SELOBJ… Есть ли возможность выделить предметом кодом, через тот же act к примеру, без прямого клика игроком на предмет в инвентаре, чтобы выделить этот самый предмет?
И макро вопрос, как проверить есть ли предмет в инвентаре, а то я что-то в документации не могу найти енто самое.

Вполне себе #2722 15.02.2026 10:25 (1 week ago)

n3m0,
Чесслово, тут надо дождаться гуру. Реально, не сильно в теме.
Я попробовал пользоваться стандартным набором инвентаря и понял, что он меня совершенно не устраивает. По сути он пустой, оболочка - не более. Можно добавить-убрать и по сути всё. Ни количества, ни других свойств. И я решил, что если все свойства надо хранить отдельно - то нахрена использовать? Я написал свой, сначала было кривовато, но терпимо (Старый пример лежит несколько страниц назад. https://qsp.org/forum/23-kak-sdelat?page=425). А теперь можно применять к любому количеству “предметов” с совершенно разными “внутренними структурами”.

Edited at 24.02.2026 17:49 (11 hours ago)

Как проверить, есть ли среди предметов предмет, содержащий такое-то слово — я вот таким кодом пользуюсь:

i=1
yes_its_here=0
:ii
  $currentObjectName=$getObj(i)

  if instr($currentObjectName,$findname):
    yes_its_here=1
  end
  if i < countObj or i = countObj:
    i+=1
    jump'ii'
  end

n3m0, событие выделения предмета, согласно вики, только по клику мышью. Какая задача стоит? Возможно, можно решить другим способом.

Log in or Register to post comments.